পার্ল অ্যারের মাধ্যমে পুনরাবৃত্তি করার সর্বোত্তম উপায়


96

পার্ল অ্যারের মাধ্যমে পুনরাবৃত্তি করার জন্য (গতি এবং মেমরির ব্যবহারের ক্ষেত্রে) সর্বোত্তম বাস্তবায়ন কোনটি? এর চেয়ে ভাল উপায় আর কি আছে? (ধরে রাখার @Arrayদরকার নেই)।

বাস্তবায়ন ঘ

foreach (@Array)
{
      SubRoutine($_);
}

বাস্তবায়ন 2

while($Element=shift(@Array))
{
      SubRoutine($Element);
}

বাস্তবায়ন 3

while(scalar(@Array) !=0)
{
      $Element=shift(@Array);
      SubRoutine($Element);
}

বাস্তবায়ন 4

for my $i (0 .. $#Array)
{
      SubRoutine($Array[$i]);
}

বাস্তবায়ন 5

map { SubRoutine($_) } @Array ;

4
কেন সেখানে একটি "সেরা" থাকবে? বিশেষত প্রদত্ত যে আপনি কীভাবে একে অপরের বিরুদ্ধে পরিমাপ করবেন তা আমাদের ধারণা নেই (মেমরি ব্যবহারের চেয়ে গতি কি আরও বেশি গুরুত্বপূর্ণ? mapএবং গ্রহণযোগ্য উত্তর? ইত্যাদি)
ম্যাক্স ল্যাববার্ট

4
আপনার পোস্ট করা তিনজনের মধ্যে দু'জন আমাকে "ডাব্লুএইচটি?!" যেতে বাধ্য করত? যদি না থাকে তবে আশেপাশের অতিরিক্ত প্রসঙ্গ হিসাবে তাদের বুদ্ধিমান বিকল্প হিসাবে তৈরি করুন। যাইহোক, এই প্রশ্নটি " দুটি সংখ্যা যুক্ত করার সর্বোত্তম উপায় কী? " এর স্তরে রয়েছে বেশিরভাগ সময়, কেবল একটি উপায় থাকে। তারপরে, সেই পরিস্থিতিগুলি রয়েছে, যেখানে আপনার অন্যরকম প্রয়োজন। ভোট বন্ধ
সিনান Ünür

4
@ সিনান্নির আমি আপনার মতের সাথে সহানুভূতি জানাই (যে দুটি সংখ্যা যুক্ত করার একমাত্র উপায় আছে), তবে উপমাটি খারিজভাবে ব্যবহার করার মতো শক্তিশালী নয়। স্পষ্টতই, একাধিক উপায় রয়েছে এবং ওপি একটি ভাল ধারণা কী এবং কোনটি নয় তা বুঝতে চায়।
কোডক্লাউন 42

4
প্রোগ্রামিং পার্লের তৃতীয় সংস্করণের 24 তম অধ্যায়ে দক্ষতার একটি বিভাগ রয়েছে যা ভাল পঠনযোগ্য। এটি বিভিন্ন ধরণের দক্ষতা যেমন সময়, প্রোগ্রামার, রক্ষণাবেক্ষণকারীকে সম্বোধন করে। বিভাগটি এই বিবৃতি দিয়ে শুরু করে "নোট করুন যে সময়ের জন্য অনুকূলিতকরণের জন্য আপনাকে কখনও কখনও স্থান বা প্রোগ্রামার দক্ষতার জন্য ব্যয় করতে পারে (নীচের বিরোধী ইঙ্গিত দ্বারা নির্দেশিত)। তাদের বিরতি।"

4
দুটি সংখ্যা যুক্ত করার জন্য একটি উপায়? আপনি যদি নিম্ন স্তরের কলগুলি / বাস্তবায়নগুলি সন্ধান করেন তবে নয় .... চিন্তাভাবনা বহন করুন, সংযোজনকারীদের সংরক্ষণ করুন ইত্যাদি
ওয়ার্কওয়াইজ

উত্তর:


76
  • গতির ক্ষেত্রে: # 1 এবং # 4, তবে বেশিরভাগ ক্ষেত্রে খুব বেশি নয়।

    আপনি নিশ্চিত করতে একটি বেঞ্চমার্ক লিখতে পারেন, তবে আমার সন্দেহ হয় যে আপনি # 1 এবং # 4 কিছুটা দ্রুত হতে পেয়েছেন কারণ পারেলের পরিবর্তে সিটিতে পুনরাবৃত্তির কাজটি করা হয়েছে এবং অ্যারে উপাদানগুলির অনাবশ্যক অনুলিপি ঘটে না। ( $_হয় ওরফে # 1 উপাদান, কিন্তু # 2 এবং # 3 আসলে কপি অ্যারে থেকে scalars।)

    # 5 একই হতে পারে।

  • পদগুলির মেমরির ব্যবহারের ক্ষেত্রে: # 5 ব্যতীত এগুলি সব একই।

    for (@a)অ্যারের সমতলকরণ এড়ানোর জন্য বিশেষ-বিশেষ লুপটি অ্যারের সূচকগুলির উপরে পুনরাবৃত্তি করে।

  • পাঠযোগ্যতার ক্ষেত্রে: # 1।

  • নমনীয়তার ক্ষেত্রে: # 1 / # 4 এবং # 5।

    # 2 মিথ্যা এমন উপাদানগুলিকে সমর্থন করে না। # 2 এবং # 3 ধ্বংসাত্মক।


4
বাহ, আপনি সংক্ষিপ্ত এবং সাধারণ বাক্যে ট্রাকের বোঝা যুক্ত করেছেন।
জয়পাল সিংহ

4
# 2 ভাল যখন আপনি সারিগুলি করেন (উদাহরণস্বরূপ প্রস্থের প্রথম অনুসন্ধানগুলি):my @todo = $root; while (@todo) { my $node = shift; ...; push @todo, ...; ...; }
ইকগামি

বাস্তবায়ন 4 সূচকগুলির একটি মধ্যবর্তী অ্যারে তৈরি করে না, যা ব্যবহারের জন্য প্রচুর পরিমাণে মেমরি প্রবর্তন করতে পারে? যদি তা হয় তবে শোনা যাচ্ছে যে কেউ এই পদ্ধতির ব্যবহার করা উচিত নয়। stackoverflow.com/questions/6440723/... rt.cpan.org/Public/Bug/Display.html?id=115863
Thorsten Schöning

@ ইকগামি আপনার চ্যাম্পিয়ন শৈলীর কাছে সত্য - দুর্দান্ত উত্তর :)
স্কিটিস্ট্যাক্স

26

আপনি যদি কেবলমাত্র উপাদানগুলির বিষয়ে যত্নশীল হন তবে @Arrayব্যবহার করুন:

for my $el (@Array) {
# ...
}

বা

সূচকগুলি গুরুত্বপূর্ণ হলে, ব্যবহার করুন:

for my $i (0 .. $#Array) {
# ...
}

বা, perl5.12.1 হিসাবে , আপনি ব্যবহার করতে পারেন:

while (my ($i, $el) = each @Array) {
# ...
}

যদি আপনার লুপের শরীরে উপাদান এবং এর সূচক উভয়ই প্রয়োজন হয়, আমি আশা করব ব্যবহার each দ্রুত হতে, তবেআপনি প্রাক-5.12.1 perlএস এর সাথে সামঞ্জস্যতা ছেড়ে দিবেন ।

এগুলি ব্যতীত অন্য কিছু প্যাটার্ন নির্দিষ্ট পরিস্থিতিতে উপযুক্ত হতে পারে।


আমি আশা করব eachধীরে ধীরে হবে। এটি অন্যের একটি কাজ করে একটি নাম, পাশাপাশি একটি তালিকা নিয়োগ, দুটি স্কেলারের অনুলিপি এবং দুটি স্কেলার ক্লিয়ারিংয়ের সমস্ত কাজ করে।
ইকেগামি

এবং, আমার পরিমাপের দক্ষতার সর্বোপরি, আপনি ঠিক বলেছেন। forঅ্যারের সূচকগুলিতে পুনরাবৃত্তির সাথে প্রায় 45% দ্রুত এবং আরে রেফারেন্সের সূচকগুলি (আমি $array->[$i]দেহে অ্যাক্সেস করি ) eachএর সাথে সংযোগে ব্যবহার করার সময় পুনরুক্তি করার সময় 20% দ্রুত while
সিনান Ünür

3

আইএমও, বাস্তবায়ন # 1 টি সাধারণ এবং পার্লের পক্ষে সংক্ষিপ্ত এবং মূর্তিমানিক হওয়ায় একা অন্যকে ট্রাম্প করে। তিনটি পছন্দের একটি মানদণ্ড আপনাকে গতি অন্তর্দৃষ্টি দিতে পারে, কমপক্ষে।


2

1 টি 2 এবং 3 এর থেকে পৃথক, যেহেতু এটি কৌশলটিতে অ্যারে ছেড়ে যায়, অন্য দুটি এটি খালি রেখে দেয়।

আমি বলতে চাই যে # 3 বেশ বেপরোয়া এবং সম্ভবত কম দক্ষ, তাই এটি ভুলে যান।

যা আপনাকে # 1 এবং # 2 দিয়ে ফেলেছে এবং তারা একই কাজ করে না, তাই একজনের চেয়ে অপরটির চেয়ে ভাল হওয়া যায় না। যদি অ্যারেটি বড় হয় এবং আপনার এটি সংরক্ষণ করার প্রয়োজন না হয় তবে সাধারণত সুযোগটি এটির সাথে ডিল করবে ( তবে দ্রষ্টব্য দেখুন ), তাই সাধারণত , # 1 এখনও পরিষ্কার এবং সহজ পদ্ধতি। প্রতিটি উপাদানকে সরিয়ে ফেললে কোনও গতি বাড়বে না। এমনকি যদি রেফারেন্স থেকে অ্যারেটি মুক্ত করার প্রয়োজন হয় তবে আমি কেবল যাব:

undef @Array;

হয়ে গেলে

  • দ্রষ্টব্য : অ্যারের স্কোপ সম্বলিত সাবরুটাইন আসলে অ্যারে রাখে এবং পরের বার স্থানটি পুনরায় ব্যবহার করে। সাধারণত , এটি জরিমানা করা উচিত (মন্তব্য দেখুন)।

@Array = ();অন্তর্নিহিত অ্যারে মুক্ত করে না। এমনকি সুযোগের বাইরে যাওয়াও তা করবে না। আপনি যদি অন্তর্নিহিত অ্যারেটি মুক্ত করতে চান তবে আপনি ব্যবহার করতে পারেন undef @Array;
ইকেগামি

4
ডেমো; perl -MDevel::Peek -e'my @a; Dump(\@a,1); @a=qw( a b c ); Dump(\@a,1); @a=(); Dump(\@a,1); undef @a; Dump(\@a,1);' 2>&1 | grep ARRAY
ইকেগামি

কি??? আমি ভেবেছিলাম জিসির পুরো পয়েন্টটি একবার রেফ গণনা ছিল == 0, জড়িত স্মৃতিটি পুনর্ব্যবহারযোগ্য হয়ে যায়।
কোডক্লাউন 42

@ আইকগামি: আমি ()বনাম সম্পর্কিত জিনিসটি দেখতে পাচ্ছি undef, তবে যদি সুযোগের বাইরে চলে যায় তবে স্থানীয়ভাবে কোনও অ্যারের দ্বারা ব্যবহৃত স্মৃতিটি সেই সুযোগে প্রকাশ না করে, কী পার্লটি কোনও ফাঁস হওয়া দুর্যোগ তৈরি করে না? যে করতে পারবে না সত্য হতে।
কোডক্লাউন 42

তারাও ফাঁস হয় না। সাবটি এখনও তাদের মালিকানাধীন রয়েছে এবং পরের বার সাবটি কল করার পরে তাদের পুনরায় ব্যবহার করবে। গতির জন্য অনুকূলিত।
ইকেগামি

1

উপাদান বা অ্যারে মুদ্রণের জন্য একক লাইনে।

(@ অ্যারে) এর জন্য print _ মুদ্রণ করুন;

দ্রষ্টব্য: মনে রাখবেন যে $ _ লুপে @ অ্যারে উপাদানটি অভ্যন্তরীণভাবে উল্লেখ করছে। $ _ এ করা যে কোনও পরিবর্তনগুলি @ অ্যারে প্রতিবিম্বিত হবে; প্রাক্তন

my @array = qw( 1 2 3 );
for (@array) {
        $_ = $_ *2 ;
}
print "@array";

আউটপুট: 2 4 6


0

এই জাতীয় প্রশ্নগুলি তাদের মানদণ্ডে স্থির করার সর্বোত্তম উপায়:

use strict;
use warnings;
use Benchmark qw(:all);

our @input_array = (0..1000);

my $a = sub {
    my @array = @{[ @input_array ]};
    my $index = 0;
    foreach my $element (@array) {
       die unless $index == $element;
       $index++;
    }
};

my $b = sub {
    my @array = @{[ @input_array ]};
    my $index = 0;
    while (defined(my $element = shift @array)) {
       die unless $index == $element;
       $index++;
    }
};

my $c = sub {
    my @array = @{[ @input_array ]};
    my $index = 0;
    while (scalar(@array) !=0) {
       my $element = shift(@array);
       die unless $index == $element;
       $index++;
    }
};

my $d = sub {
    my @array = @{[ @input_array ]};
    foreach my $index (0.. $#array) {
       my $element = $array[$index];
       die unless $index == $element;
    }
};

my $e = sub {
    my @array = @{[ @input_array ]};
    for (my $index = 0; $index <= $#array; $index++) {
       my $element = $array[$index];
       die unless $index == $element;
    }
};

my $f = sub {
    my @array = @{[ @input_array ]};
    while (my ($index, $element) = each @array) {
       die unless $index == $element;
    }
};

my $count;
timethese($count, {
   '1' => $a,
   '2' => $b,
   '3' => $c,
   '4' => $d,
   '5' => $e,
   '6' => $f,
});

এবং এটি পার্ল 5, সংস্করণ 24, x86_64-linux-gnu- থ্রেড-মাল্টির জন্য নির্মিত সাবভার্সন 1 (v5.24.1) এ চলছে

আমি পাই:

Benchmark: running 1, 2, 3, 4, 5, 6 for at least 3 CPU seconds...
         1:  3 wallclock secs ( 3.16 usr +  0.00 sys =  3.16 CPU) @ 12560.13/s (n=39690)
         2:  3 wallclock secs ( 3.18 usr +  0.00 sys =  3.18 CPU) @ 7828.30/s (n=24894)
         3:  3 wallclock secs ( 3.23 usr +  0.00 sys =  3.23 CPU) @ 6763.47/s (n=21846)
         4:  4 wallclock secs ( 3.15 usr +  0.00 sys =  3.15 CPU) @ 9596.83/s (n=30230)
         5:  4 wallclock secs ( 3.20 usr +  0.00 sys =  3.20 CPU) @ 6826.88/s (n=21846)
         6:  3 wallclock secs ( 3.12 usr +  0.00 sys =  3.12 CPU) @ 5653.53/s (n=17639)

সুতরাং 'foreach (@ অ্যারে)' অন্যদের থেকে প্রায় দ্বিগুণ দ্রুত। অন্য সবগুলিও একই রকম।

@ ইকগামি আরও উল্লেখ করেছেন যে গতি ব্যতীত এই প্রতিচ্ছবিগুলির মধ্যে বেশ কয়েকটি পার্থক্য রয়েছে।


4
তুলনাটি $index < $#arrayআসলে হওয়া উচিত $index <= $#arrayকারণ $#arrayঅ্যারের দৈর্ঘ্য নয় এটির শেষ সূচক।
জোশ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.