هل يمكنك فرض إما أن يكون المرجع العددي أو المصفوفة مصفوفة في بيرل؟

StackOverflow https://stackoverflow.com/questions/3112

  •  08-06-2019
  •  | 
  •  

سؤال

لدي متغير بيرل $results الذي يتم إرجاعه من الخدمة.من المفترض أن تكون القيمة مصفوفة، و $results يجب أن يكون مرجعا للصفيف.ومع ذلك، عندما تحتوي المصفوفة على عنصر واحد فقط، $results سيتم تعيينه على هذه القيمة، وليس على مصفوفة مرجعية تحتوي على هذا العنصر.

أريد أن أفعل foreach حلقة على المصفوفة المتوقعة.دون التدقيق ref($results) eq 'ARRAY', ، هل هناك أي طريقة للحصول على شيء يعادل ما يلي:

foreach my $result (@$results) {
    # Process $result
}

سيعمل نموذج التعليمات البرمجية المعين هذا مع المرجع، ولكنه سيشكو من العددية البسيطة.

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

هل كانت مفيدة؟

المحلول

لست متأكدًا من وجود أي طريقة أخرى غير:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....

نصائح أخرى

هناك حل آخر يتمثل في التفاف المكالمة إلى الخادم وجعله يعيد دائمًا مصفوفة لتبسيط بقية حياتك:

sub call_to_service
{
    my $returnValue = service::call();

    if (ref($returnValue) eq "ARRAY")
    {
        return($returnValue);
    }
    else
    {
       return( [$returnValue] );
    }
}

ومن ثم يمكنك دائمًا معرفة أنك ستستعيد مرجعًا إلى مصفوفة، حتى لو كان عنصرًا واحدًا فقط.

foreach my $item (@{call_to_service()})
{
  ...
}

حسناً، إذا كنت لا تستطيع أن تفعل...

for my $result ( ref $results eq 'ARRAY' ? @$results : $results ) {
    # Process result
}

أو هذا...

for my $result ( ! ref $results ? $results : @$results ) {
    # Process result
}

إذن قد تضطر إلى تجربة شيء مخيف مثل هذا!....

for my $result ( eval { @$results }, eval $results ) {
    # Process result
}

ولتجنب تقييم السلسلة الخطير هذا، يصبح الأمر قبيحًا حقًا!!....

for my $result ( eval { $results->[0] } || $results, eval { @$results[1 .. $#{ $results }] } ) {
    # Process result
}

ملاحظة.أفضّل أن أقوم بتجريده بعيدًا في مثال call_to_service() الفرعي المقدم من reatmon.

سأعيد تحليل الكود داخل الحلقة ثم أفعل ذلك

if( ref $results eq 'ARRAY' ){
    my_sub($result) for my $result (@$results);
}else{
    my_sub($results);
}

بالطبع سأفعل ذلك فقط إذا كان الكود الموجود في الحلقة غير تافه.

لقد اختبرت هذا للتو مع:

#!/usr/bin/perl -w
use strict;

sub testit {

 my @ret = ();
 if (shift){
   push @ret,1;
   push @ret,2;
   push @ret,3;
}else{
  push @ret,"oneonly";
}

return \@ret;
}

foreach my $r (@{testit(1)}){
  print $r." test1\n";
}
foreach my $r (@{testit()}){
   print $r." test2\n";
}

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

يمكنك القيام بذلك على النحو التالي:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top