2017-09-19 14 views
5

Je voudrais utiliser suivant pour créer des emplois uniques, où {1} et {2} sont tuples uniques:GNU combinatoires parallèle, l'utilisation de la liste des arguments à plusieurs reprises

parallel echo {1} {2} ::: A B C D ::: A B C D 

Par exemple, dans python (itertools) fournit un tel générateur combinatoire:

permutations('ABCD', 2) 

AB AC AD BC BA BD CA CB CD DA DB DC


Existe-t-il un moyen de l'implémenter directement via bash? Ou GNU parallèle lui-même? Peut-être ignorer des tâches redondantes en quelque sorte? Mais alors, comment puis-je vérifier quelles combinaisons de paramètres ont déjà été utilisées.

parallel echo {= 'if($_==3) { skip() }' =} ::: {1..5} 
+1

une option serait de stocker les données dans un tableau, et d'appliquer à ses indices d'une stratégie détaillée: https://stackoverflow.com/a/21697322/5351549 – ewcz

+0

Est-ABCD la arguments réels ou sont juste des détenteurs de place? Voyant la liste d'arguments réels aiderait parce que les solutions qui fonctionnent pour ABCD pourraient ne pas fonctionner pour d'autres types d'arguments – damienfrancois

Répondre

0

Une solution laide: utiliser Python pour générer la séquence et l'option --link (ou --xapply):

$ parallel --xapply echo {1} {2} ::: $(python -c "from itertools import permutations ; print(' ::: '.join([' '.join(_) for _ in zip(*list(permutations('ABCD',2)))]))") 
A B 
A C 
A D 
B A 
B C 
B D 
C A 
C B 
C D 
D A 
D B 
D C 
0

Vous pouvez utiliser deux fois parallel si vous ne me dérange pas:

# filter the first's parallel output for accepted combinations and pipe into a 2nd parallel 
parallel echo {1} {2} ::: a b c ::: a b c | awk '{ if ($1 != $2) {print $0}}' | parallel echo this is the actual {1} {2} 

# no one-liner for better maintenance 
parallel echo {1} {2} ::: a b c ::: a b c | awk '{ if ($1 != $2) {print $0}}' > myargs 
parallel --arg-file myargs echo {1} {2} 
rm myargs 

# Output is in both cases 
a b 
a c 
b a 
b c 
c a 
c b 
2

Si les valeurs sont uniques:

parallel echo {= 'if($arg[1] eq $arg[2]) { skip() }' =} ::: A B C D ::: A B C D 

Ou plus généralement:

parallel echo \ 
    '{= my %seen; for my $a (@arg) { $seen{$a}++ and skip() } =}' \ 
    ::: A B C D ::: A B C D ::: A B C D 

Si vous voulez traiter AB comme BA alors ce ne fonctionne que l'une des combinaisons:

parallel echo \ 
    '{= for my $t (2..$#arg) { if($arg[$t-1] ge $arg[$t]) { skip() } } =}' \ 
    ::: A B C D ::: A B C D ::: A B C D 

Si vous utilisez ces beaucoup, souvenez-vous que vous pouvez utiliser --rpl à faire vos propres chaînes de remplacement en mettant ceci dans ~/.parallel/config

--rpl '{unique} my %seen; for my $a (@arg) { $seen{$a}++ and skip() }' 
--rpl '{choose_k} for my $t (2..$#arg) { if($arg[$t-1] ge $arg[$t]) { skip() } }' 

Et puis exécutez:

parallel echo {unique} ::: A B C D ::: A B C D ::: A B C D 
parallel echo {choose_k} ::: A B C D ::: A B C D ::: A B C D 
+0

Je pense que c'est la bonne solution. Je suis seulement venu avec le mien parce que '' echo parallèle {= 'si ($ arg [1] == $ arg [2]) {skip()}' =} ::: ABCD ::: ABCD'' n'a pas fais le tour et je n'étais pas au courant de '' eq''. Dans zsh, vous devez écrire '' "{= perl expression =}" '' (c'est-à-dire entourer de guillemets doubles). – Rolf