配列要素の組み合わせを見つけるシェルスクリプト

配列要素の組み合わせを見つけるシェルスクリプト

配列が定義されたシェルスクリプトがあります。配列には2つ以上の要素が含まれています。配列のすべての要素の組み合わせを見つける必要があります。私の配列に要素があるとしましょう。{12345, 56789, 98765}、出力を取得しようとしています。

12345, 56789
12345, 98765
56789, 98765

私はPHPコードを試しましたここ

<?php
function pc_permute($items, $perms = array( )) {
    if (empty($items)) {
        print join(' ', $perms) . "\n";
    }  else {
        for ($i = count($items) - 1; $i >= 0; --$i) {
             $newitems = $items;
             $newperms = $perms;
             list($foo) = array_splice($newitems, $i, 1);
             array_unshift($newperms, $foo);
             pc_permute($newitems, $newperms);
         }
    }
}
pc_permute(split(' ', '12345 56789 98765'));
?>

私が得た結果は次のとおりです。

12345 56789 98765
56789 12345 98765
12345 98765 56789
98765 12345 56789
56789 98765 12345
98765 56789 12345

2つの要素サイズの出力の組み合わせを取得できますか?順序は関係ありません。A B組み合わせで得られるので、その逆は必要ありません(B A)。

答え1

あなたに必要なのはprintf.それだけですprint function。そしてそれがまさにそれです。

printf '%s\t%s\n' ${array[@]}

あなたはそうします:

( set -- 12345 56789 98765; for i ; do 
    eval set -- $(printf '"$%s" ' `seq 2 $#` 1)
    echo "$*"
done )

出力

56789 98765 12345
98765 12345 56789
12345 56789 98765

そうする必要はありませんeval。それは愚かなことです。より良い方法は次のとおりです。

( set -- 12345 56789 98765 ; 
until [ $((i=i+1)) -gt $# ] ; do
    set -- $(s=$1 ; shift ; printf '%s\n' "$@" "$s")
    printf '%s ' "$@" ; echo
done)

出力

56789 98765 12345
98765 12345 56789
12345 56789 98765

その後、2つの要素のみを必要に応じて少し変更するだけです。 1行だけ追加してください。

( set -- 12345 56789 98765 ;
    until [ $((i=i+1)) -ge $# ] ; do
        set -- $(s=$1 ; shift ; printf '%s\n' "$@" "$s")
        v="${v}$(printf '%s ' "$@")"
    done ; printf "%s\t%s\n" $v
    )

出力

56789   98765
12345   98765
12345   56789

私はいつもそうしますが、決して恥ずかしくはありません。私はいつも実際のシェル配列を使って作業しているので、それを学ぶのに数分かかりました。

以下は、他の答えのために私が書いた小さなスクリプトです。

    abc="a b c d e f g h i j k l m n o p q r s t u v w x y z"
for l in $abc ; do { 
        h= c= ; [ $((i=i+1)) -gt 26 ] && n=$((n+26)) i=
    xyz=$(x=${xyz:-$abc} ;\
        printf %s\\n ${x#?} $l)
    mid=$(set -- $xyz ; eval echo \$$((${#}/4))) ;\
        echo "$mid $l" >&2 ;
        [ $(((i+n)%${mod=3})) -eq 0 ] && c="$mid" h="${xyz%"$mid"*}"
    line="$(printf '%s ' $h $c ${xyz#"$h"})"
    printf "%s$(printf %s ${xyz#?}${mid})\n" \
        ${line} >|/tmp/file$((i+n))
} ; done

これにより、26個のファイルが作成されます。これは次のとおりです。各ファイルについて増加しました。

bcdefghijklmnopqrstuvwxyzag
ccdefghijklmnopqrstuvwxyzag
dcdefghijklmnopqrstuvwxyzag
ecdefghijklmnopqrstuvwxyzag
fcdefghijklmnopqrstuvwxyzag
gcdefghijklmnopqrstuvwxyzag
hcdefghijklmnopqrstuvwxyzag
icdefghijklmnopqrstuvwxyzag
jcdefghijklmnopqrstuvwxyzag
kcdefghijklmnopqrstuvwxyzag
lcdefghijklmnopqrstuvwxyzag
mcdefghijklmnopqrstuvwxyzag
ncdefghijklmnopqrstuvwxyzag
ocdefghijklmnopqrstuvwxyzag
pcdefghijklmnopqrstuvwxyzag
qcdefghijklmnopqrstuvwxyzag
rcdefghijklmnopqrstuvwxyzag
scdefghijklmnopqrstuvwxyzag
tcdefghijklmnopqrstuvwxyzag
ucdefghijklmnopqrstuvwxyzag
vcdefghijklmnopqrstuvwxyzag
wcdefghijklmnopqrstuvwxyzag
xcdefghijklmnopqrstuvwxyzag
ycdefghijklmnopqrstuvwxyzag
zcdefghijklmnopqrstuvwxyzag
acdefghijklmnopqrstuvwxyzag

答え2

2つの要素サイズの組み合わせで要素を印刷する方法を見つけました。 PHPコードは次のとおりです。

<?php
function pc_array_power_set($array) {
    // initialize by adding the empty set
    $results = array(array( ));

    foreach ($array as $element)
        foreach ($results as $combination)
            array_push($results, array_merge(array($element), $combination));
    return $results;
}
$set = array('12345', '56789', '98765');
$power_set = pc_array_power_set($set);
foreach (pc_array_power_set($set) as $combination) {
    if (2 == count($combination)) {
        print join("\t", $combination) . "\n";
    }
}
?>

上記のコードは出力を次のように印刷します。

56789   12345
98765   12345
98765   56789

上記のコードへの参照は次のとおりです。ここ

関連情報