2012-05-25 21 views
15

私はawkが連想配列を持っていることを認識し、これにawkの同等がある場合、私は疑問に思う:インデックスを指定せずにawkの配列に項目を追加することはできますか?

http://php.net/manual/en/function.array-push.php

明白な回避策はちょうど言うことです:

array[$new_element] = $new_element 

しかし、これはそう読みにくく、ハッキングされている必要があります。

+2

私はそれをエレガントでミニマルなものと呼んでいます。ハックではありません。 ;-)。配列を管理するための独自の関数を書くことはできますが、そのための言語には何も組み込まれていません。がんばろう。 – shellter

答えて

8

awkで配列の長さがすぐに利用できるとは思いません(少なくとも、私が使っているバージョンではありません)。しかし、あなたは、単に長さを維持して、このような何か行うことができます:

array[arraylen++] = $0; 

をし、同じ整数値を経由して要素にそれをアクセス:gawk

for (i = 0; i < arraylen; i++) 
    print array[i]; 
+0

+1 - GAWKの 'length()'関数は配列内の要素の数を返しますが、配列はまばらなので長さは必ずしも最後の要素ではありません。 –

+1

歴史的な参考のために、 'length(arrayname)'表記はGAWK専用ではありません。 2002年にOne True Awkに追加されました。この機能がgawk [3年後](http: //code.metager.de/source/xref/gnu/gawk/ChangeLog.0#3453)。 – ghoti

6

あなたは、配列の長さを見つけることができますlength(var)であなた自身の機能を調理することはそれほど難しくありません。

function push(A,B) { A[length(A)+1] = B } 

かかわらお知らせこの議論、:http://objectmix.com/awk/361598-gawk-length-array-question.html - 私は今アクセスできるすべての場所では当たり前、gawkの3.1.5を持っているので、私はきちんと私の機能をテストすることはできません。しかし近似があります。

vnix$ gawk '# BEGIN: make sure arr is an array 
> BEGIN { delete arr[0] } 
> { print "=" length(arr); arr[length(arr)+1] = $1; 
>  print length(arr), arr[length(arr)] } 
> END { print "---"; 
>  for (i=1; i<=length(arr); ++i) print i, arr[i] }' <<HERE 
> fnord foo 
> ick bar 
> baz quux 
> HERE 
=0 
1 fnord 
=1 
2 ick 
=2 
3 baz 
--- 
1 fnord 
2 ick 
3 baz 
+1

'A [length(A)+1]スニペットは衝突を避けることはできません。あなたの例のように、予測可能な順序で配列に物事を追加する場合にのみ機能します。ただし、配列要素を削除する場合は、 'length()'を減らすギャップを作成し、最も高い数字をそのまま残してください。 – ghoti

1

他にも述べたように、awkはこのような機能を何も備えていません。あなたの "ハックアップ"回避策は、いくつかのデータセットでは動作しますが、他のデータセットでは動作しません。同じ配列値を2回追加し、配列内で2回表現したいと考えてください。

$ echo 3 | awk 'BEGIN{ a[1]=5; a[2]=12; a[3]=2 } 
> { a[$1] = $1 } 
> END {print length(a) " - " a[3]}' 
3 - 3 

データが配列に含まれていると、最適な解決方法が通知される場合がありますが、ここにはいくつかの考えがあります。

最初にインデックスが常に数値であることが確実であれば、常に1から始まり、配列要素を削除しないと、トリプルの提案A[length(A)+1]="value"が役立ちます。しかし、要素を削除すると、次の書き込みが最後の要素を上書きすることがあります。

インデックスがでも問題がなく、長いキーでスペースを無駄にする心配がない場合は、衝突の可能性を減らすのに十分な長さの乱数を使用できます。迅速な&汚いオプションは、次のようになります。

srand() 
a[rand() rand() rand()]="value" 

は、より良いランダム化srand()を使用することを忘れないでください、そして実際の乱数を生成するためにrand()を信用していません。これは多くの点で完璧ではないソリューションですが、コードの単一行であるという利点があります。

あなたの鍵はtripleeeのソリューションを破るの例のように、あなたはプッシュ機能に小さな検索を追加することができ、数値が、おそらくスパースある場合:

function push (a, v,  n) { 
    n=length(a)+1 
    while (n in a) n++ 
    a[n]=v 
} 

whileループは、そのあなたの」保証未使用のインデックスを割り当てます。この関数は数値以外のインデックスを使用する配列とも互換性があります。の数値キーを割り当てますが、既に存在するものは気にしません。

awkは配列内の要素の順序を保証しないので、「配列の最後にアイテムを押し込む」という考え方は間違っています。 この要素を配列に追加しますが、forループを実行すると最後に表示されるという保証はありません。

$ cat a 
#!/usr/bin/awk -f 

function push (a, v,  n) { 
    n=length(a)+1 
    while (n in a) n++ 
    a[n]=v 
} 

{ 
    push(a, $0) 
} 

END { 
    print "length=" length(a) 
    for(i in a) print i " - " a[i] 
} 

$ printf '3\nfour\ncinq\n' | ./a 
length=3 
2 - four 
3 - cinq 
1 - 3 
関連する問題