سؤال

كيف أجعل المصفوفة أقصر في بيرل؟قرأت بعض صفحات الويب التي تشير إلى أنه يمكنني التعيين:

$#ARRAY = 42;

قرأت أن استخدام $# تم إهماله.أحتاج إلى حل يناسب مجموعة من المصفوفات أيضًا.هذا لم ينجح:

$#$ARRAY[$i] = 42;
هل كانت مفيدة؟

المحلول

لست على علم بالتكليف $#ARRAY يتم إهمالها؛ perldoc perldata من 5.10.0 بالتأكيد لا يقول شيئًا عن ذلك.إنها أسرع طريقة لاقتطاع مصفوفة.

إذا كنت تريد شيئًا أكثر قابلية للقراءة، فاستخدمه splice:

splice @ARRAY, 43;

(ملحوظة 43 بدلاً من 42 - $#ARRAY تحصل على الفهرس الأخير للمصفوفة، بينما splice يأخذ طول من المصفوفة بدلاً من ذلك).

أما بالنسبة للعمل على صفائف من المصفوفات، أفترض أنك تقصد القدرة على اقتطاع مجموعة متداخلة عبر مرجع؟في هذه الحالة تريد:

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

أو

splice @{$ARRAY->[7]}, 43;

نصائح أخرى

خياراتك لا حدود لها تقريبًا (لقد حددت خمسة طرق هنا) ولكن استراتيجيتك سيتم تحديدها وفقًا لاحتياجاتك وأهدافك المحددة بالضبط.(جميع الأمثلة ستحول @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);

غير مرغوب فيه في جميع الحالات تقريبًا، إلا إذا كنت تحب الحذف ():

#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

ال $# تم إهمال المتغير، ولكن $#array الميزة ليست كذلك.

لاستخدام ال $#array بناء جملة على تعبير عشوائي ينتج عنه مرجع صفيف، افعل $#{ EXPR }.

شاهد ما لا يقدر بثمن: http://perlmonks.org/?node=References+quick+reference

لقد قدمت الإجابة الأساسية بنفسك.يمكنك تقصير مصفوفة عن طريق تعيين الفهرس الأخير:

$#Array = 42

تدوين $#Foo للإشارة إلى الفهرس الأخير في المصفوفة هو مطلقًا لا إهمال.وبالمثل، لن يتم إهمال التعيين إليه أيضًا.نقلا عن وثائق بيرلداتا:

طول المصفوفة هو قيمة عددية. قد تجد طول الصفيف @أيام من خلال تقييم أيام $#, ، كما هو الحال في CSH.ومع ذلك ، هذا ليس طول الصفيف.إنه فردي للعنصر الأخير ، وهو قيمة مختلفة نظرًا لوجود عنصر 0. تعيين إلى $#أيام يغير في الواقع طول الصفيف. تقصير صفيف بهذه الطريقة يدمر القيم المتداخلة.إن إطالة صفيف تم تقصيره مسبقًا لا يستعيد القيم التي كانت في تلك العناصر.(اعتاد أن تفعل ذلك في بيرل 4 ، لكن اضطررنا إلى كسر هذا للتأكد من استدعاء المدمرين عند توقعهم.)

  • $#array هو الفهرس الأخير من المصفوفة.
  • $#$مصفوفة سيكون الفهرس الأخير للمصفوفة أشار إلى بواسطة صفيف $.
  • $#$array[$i] يعني أنك تحاول فهرسة عددية - لا يمكن القيام بذلك.$#{$array[3]} يحل مشكلة اشتراك المصفوفة الرئيسية بشكل صحيح قبل أن نحاول الرجوع إلى الفهرس الأخير.
  • تستخدم وحدها

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

    يعين طول 9 إلى تم تنشيطه تلقائيًا المصفوفة في $array[3].

  • عندما تكون في شك، استخدم Data::Dumper:

    use Data::Dumper;
    $#{$array[3]} = 5;
    $#array       = 10;
    print Dumper( \@array, $array ), "\n";
    

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

يمكنك أن تفعل

splice @array, $length;
#or
splice @{$arrays[$i]}, $length;

هناك طريقتان لتفسير السؤال.

  • كيفية تقليل طول المصفوفة؟
  • كيفية تقليل مقدار الذاكرة التي تستهلكها المصفوفة؟

معظم الإجابات حتى الآن تركز على الأول.من وجهة نظري أفضل إجابة على ذلك هي لصق او جمع وظيفة.على سبيل المثال، لإزالة 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));
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top