配列の補数をお探しですか?

配列の補数をお探しですか?

次からこの問題、ファイルからランダムな10行を抽出したかったので、残りの90行を別々のファイルにしたいと思います。

ドキュメントには 1 から 100 までのインデックスがある 100 行があるので、問題は find の補数で帰結しますind1, 2, ..., 100

ind=$(shuf -i 1-100 -n 10 | sort -n)

だから私の質問は

  1. 1, 2, ..., 100配列を効率的に生成する方法は?そして
  2. 完成するのに使えるようですcomm。それでは、commファイルの代わりに配列をどのように処理する必要がありますか?

答え1

他のスレッドの私の提案に基づいて:

awk '
  BEGIN { srand(); do a[int(100*rand()+1)]; while (length(a)<10) }
  NR in a
' ~/orig.txt > ~/short.txt

これを変更して2つのファイルを作成できます。

awk -v range=100 -v offset=1 -v amount=10 '
  BEGIN { srand(); do a[int(range*rand()+offset)]; while (length(a)<amount) }
  NR in a    { print > "short.txt" }
  !(NR in a) { print > "rest.txt" }
' ~/orig.txt

(これは内部的にはawk使用できません~。ただし、HOMEthroughはENVIRON[]次のように使用できます:print > ENVIRON["HOME"] "/short.txt"またはresp., print > ENVIRON["HOME"] "/rest.txt".)

答え2

さて、もう一度考えてみましょう - 私は仕事をしました。方法とても難しいです。必要なのはこれだけです:

shuf -i 1-100 -n10 |
sed 's/$/{p;b\n}/' |
sed -nf - -e 'w separate_file' infile >outfile

n交換の代わりにリテラル改行文字が必要な場合がありますsed。とにかく、これは以下のようなことをします。他の90行すべてを実行するのを妨げることはありません。ファイルにあるので、その場にあるだけなので、特に考慮する必要はありません。

完全な取引は次のとおりです。

set  " $(shuf -i 1-100 -n 10) "
while [ "$((i+=1))" -le 100 ]
do    [ -z "${1##*[!0-9]$i[!0-9]*}" ]
      printf "$i%.$((!$?))s%.$?s\n" p H 
done| sed -nf - -e '$!d;x;s/.//p' <infile >outfile

デフォルトでは、sed次のスクリプトを作成します。

1H
2H
3H
4p
5H
...
90p
91H
...

そして100まで続く。最後の行から - ランダムに選択されたすべての行がp印刷されたら、前のスペースxに変更し、最初に挿入されたewline文字を置き換えて残りを印刷します。Hs///\np

シェルループなしでこれを行うには、次のようにします。

set  "$(shuf -i 1-100 -n 10)"
{ seq 100 | grep -Fxv "$1"; echo "$1"; } |
sed '1,90s/$/H/;91,$s/$/p/' |
sed -nf - -e '$!d;x;s/.//p' <infile >outfile

しかし、この規模ではそれが役に立つかどうかはわかりません。

とにかくseq 100出力ファイルをテストして実行してみて出力してみたが…

3
4
5
19
57
63
64
73
80
88
1
2
6
7
8
9
10
11
12
13
14
15
16
...

...初期ランダム100に含まれていないすべての行に対して最大100です。

答え3

bashを使用する別の解決策は次のとおりです。まず、ind変数から配列を作成できます。

ind=($(shuf -i 1-100 -n 10 | sort -n))

1..100の範囲の数値を含む配列を作成する簡単な方法は次のとおりです。

numbers=({1..100})

補足を得るには uniq -u を使います。このコマンドは、ソートされたリスト内のすべての重複項目をソートします。最後の貼り付けコマンドは、すべての値を1行に戻します。

complement=($(echo ${ind[*]} ${numbers[*]} | sed 's/ /\n/g' | sort -n | uniq -u | paste -sd " " - ))
echo ${complement[*]}

質問をもう一度考えてみると、これらすべてはbash配列なしで実行できます。

ind=$(shuf -i 1-100 -n 10 | sort -n)
echo $ind {1..100} | sed 's/ /\n/g' | sort -n | uniq -u | paste -sd " " -

答え4

コマンドラインからすべてのことができると確信していますが、実際のプログラミング言語を使用すると、いくつかの問題をよりよく解決できます。たとえば、問題に対するPythonベースのソリューションは次のとおりです。

import random
import pprint

with open("file.txt", "w") as f:
  # create a file filled with numbers from 00 to 99
  f.writelines(map(lambda x: "%02d\n" % x, range(100)))

with open("file.txt") as f:
  # read it and assign each line to array, strip newlines 
  ar = set(map(lambda x: x.strip(), f.readlines()))

selection = set(random.sample(ar, 10))
rest = ar - selection

pprint.pprint(selection)
pprint.pprint(rest)

関連情報