13

Perlで配列を短くするにはどうすればよいですか? 割り当てることができることを示すいくつかの Web ページを読みました。

$#ARRAY = 42;

$# の使用は推奨されていないことを読みました。配列の配列でも機能するソリューションが必要です。これはうまくいきませんでした:

$#$ARRAY[$i] = 42;
4

8 に答える 8

19

割り当て$#ARRAYが非推奨になっていることを認識していません。perldoc perldatafrom 5.10.0 確かにそれについて何も言いません。これは、配列を切り捨てる最も速い方法です。

もう少し読みやすいものが必要な場合は、次を使用しますsplice

splice @ARRAY, 43;

( -43の代わりに注意してください。配列の最後のインデックスを取得しますが、代わりに配列の長さを取得します)。42$#ARRAYsplice

配列の配列の操作に関しては、参照を介してネストされた配列を切り捨てることができるということですか? その場合、次のことが必要です。

$#{$ARRAY->[7]} = 42;

また

splice @{$ARRAY->[7]}, 43;
于 2008-09-18T14:20:03.353 に答える
10

あなたの選択肢はほぼ無限です(私はここで5つのアプローチを概説しました)が、あなたの戦略はあなたの特定のニーズと目標が正確に何であるかによって決定されます。(すべての例は、@arrayを$N以下の要素を持つように変換します)


[編集]

他の人が指摘しているように、元の質問で提案された方法は実際には非推奨ではなく、最速で最も簡潔なソリューションを提供しますが、必ずしも最も読みやすいソリューションであるとは限りません。 また、空の要素を持つ$N未満の要素の配列を拡張するという副作用もあります

$#array = $N-1;

最小コード:

#best for trimming down large arrays into small arrays
@array = $array[0..($N-1)];

大きな配列から小さな数をトリミングするのに最も効率的です。

#This is a little less expensive and clearer
splice(@array, $n, @#array);

delete()が本当に好きでない限り、ほとんどすべての場合に望ましくありません。

#this is the worst solution yet because it requires resizing after the delete
while($N-1 < $#array)
{
   delete(array[$i]);
}

リストの残りの部分を逆の順序で必要とする場合に便利です。

#this is better than deleting because there is no resize
while($N-1 < $#array)
{
    pop @array;
    #or, "push $array2, pop @array;" for the reverse order remainder
}

長期的に時間を節約するのに便利です:

#don't put more values into the array than you actually want
于 2008-09-18T14:17:22.907 に答える
7

$#変数は非推奨になりましたが、機能$#arrayは非推奨ではありません。

$#array配列参照を生成する任意の式で構文を使用するには、を実行します$#{ EXPR }

貴重なものを参照してください:http://perlmonks.org/?node = References + quick + reference

于 2008-09-18T16:20:01.473 に答える
5

あなたは基本的に自分で標準的な答えを出しました。最後のインデックスを設定して配列を短縮します。

$#Array = 42

配列の最後のインデックスを示す $#Foo 表記は、まったく推奨ではありません。同様に、それに割り当てることも非推奨にはなりません。perldata ドキュメントの引用:

配列の長さはスカラー値です。 csh のように$#days を評価することで、配列 @days の長さを見つけることができます。ただし、これは配列の長さではありません。これは最後の要素の添え字であり、通常は 0 番目の要素があるため、異なる値です。 $#days に代入すると、実際には配列の長さが変わります。 このように配列を短くすると、間にある値が破壊されます。以前に短縮された配列を長くしても、それらの要素にあった値は復元されません。(Perl 4 ではそうしていましたが、予期したときにデストラクタが呼び出されるようにするために、これを壊さなければなりませんでした。)

于 2008-09-18T14:48:28.700 に答える
2
  • $#array は配列の最後のインデックスです。
  • $##$arrayは、$array が指す配列の最後のインデックスになります。
  • $#$array[$i] は、スカラーのインデックスを作成しようとしていることを意味します。実行できません。$#{$array[3]} は、最後のインデックスを参照する前に、メイン配列の添え字を適切に解決します。
  • 単独で使用

    $#{$array[3]} = 9;

    $array[3] で自動有効化された配列に長さ 9 を割り当てます。

  • 疑わしい場合は、Data::Dumper を使用してください。

    use Data::Dumper;
    $#{$array[3]} = 5;
    $#array       = 10;
    print Dumper( \@array, $array ), "\n";
    
于 2008-09-18T14:26:02.747 に答える
0

$#{$ARRAY[$i]} = 42;

于 2008-09-18T14:10:57.040 に答える
0

あなたができる

splice @array, $length;
#or
splice @{$arrays[$i]}, $length;
于 2008-09-18T14:12:44.417 に答える
0

質問の解釈には 2 つの方法があります。

  • 配列の長さを減らす方法は?
  • 配列によって消費されるメモリの量を減らす方法は?

これまでの回答のほとんどは、前者に焦点を当てています。私の見解では、それに対する最良の答えはsplice関数です。たとえば、末尾から 10 個の要素を削除するには、次のようにします。

splice @array, -10;

しかし、Perl が配列のメモリーを管理する方法のため、配列がより少ないメモリーを使用することを保証する唯一の方法は、それを新しい配列にコピーすることです (そして、古い配列のメモリーを再利用させます)。このために、スライス操作を使用することを考える傾向があります。たとえば、10 個の要素を削除するには:

@new = @old[ 0 .. $#old - 10 ]

500 要素の配列 (2104 バイトを使用) に対するさまざまなアプローチの比較を次に示します。

  original: length  500 => size 2104
     pound: length  490 => size 2208
    splice: length  490 => size 2104
    delete: length  490 => size 2104
     slice: length  490 => size 2064

スライス操作 (新しい配列にコピーされたもの) のみが元のサイズよりも小さいことがわかります。

この分析に使用したコードは次のとおりです。

use strict;
use warnings;
use 5.010;
use Devel::Size qw/size/;

my @original = (1 .. 500);
show( 'original', \@original );

my @pound = @original;
$#pound = $#pound - 10;
show( 'pound', \@pound );

my @splice = @original;
splice(@splice,-10);
show( 'splice', \@splice);

my @delete = @original;
delete @delete[ -10 .. -1 ];
show( 'delete', \@delete );

my @slice = @original[0 .. $#original - 10];
show( 'slice', \@slice);

sub show {
    my ($name, $ref) = @_;
    printf( "%10s: length %4d => size %d\n", $name, scalar @$ref, size($ref));
}
于 2008-09-18T18:20:39.920 に答える