2010-04-07 36 views
7

मेरे पास दो सरणी हैं, @a और @b। मैं दो सरणी के तत्वों के बीच तुलना करना चाहता हूं।मैं पर्ल में सरणी की तुलना कैसे कर सकता हूं?

my @a = qw"abc def efg ghy klm ghn"; 
my @b = qw"def ghy jgk lom com klm"; 

यदि कोई तत्व मिलान करता है तो ध्वज सेट करता है। क्या ऐसा करने का कोई आसान तरीका है?

+4

क्योंकि आपका प्रश्न अस्पष्ट है, आपको दो प्रकार के उत्तर मिल रहे हैं: (1) जो जोड़ी के मिलान की खोज करते हैं, जैसे '$ a [$ i] eq $ b [$ i] '; और (2) जो किसी भी मैच की खोज करते हैं, जैसे '$ a [$ i] eq $ b [$ j] '। आपका लक्ष्य क्या है? – FMc

+0

http://stackoverflow.com/questions/1609467/in-perl-is-there-a-built-in-way-to-compare-two-arrays-for-equality –

+0

@Sinan का संभावित डुप्लिकेट: यह प्रश्न आपको "संभावित डुप्लिकेट" के रूप में चिह्नित इस जैसा नहीं है। यह दो सरणी के सभी तत्वों की तुलना करने के बारे में है, लेकिन यह एक आम तत्व खोजने के बारे में है। –

उत्तर

9

पहले, अपने 2 सरणियों सही ढंग से लिखे जाने की जरूरत है।

@a = ("abc","def","efg","ghy","klm","ghn"); 
@b = ("def","efg","ghy","klm","ghn","klm"); 

सभी का दूसरा, मनमाने ढंग से सरणियों (जैसे सरणियों जिसका तत्वों अन्य डेटा संरचना के लिए संदर्भ हो सकता है) आप Data::Compare उपयोग कर सकते हैं के लिए।

उन तत्वों के लिए जिनके तत्व स्केलर हैं, आप List::MoreUtilspairwise BLOCK ARRAY1 ARRAY2 का उपयोग करके तुलना कर सकते हैं, जहां ब्लॉक आपकी तुलना subroutine है। आप pairwise का अनुकरण कर सकते हैं के माध्यम से (यदि आप सूची :: MoreUtils पहुँच नहीं है):

if (@a != @b) { 
    $equals = 0; 
} else { 
    $equals = 1; 
    foreach (my $i = 0; $i < @a; $i++) { 
     # Ideally, check for undef/value comparison here as well 
     if ($a[$i] != $b[$i]) { # use "ne" if elements are strings, not numbers 
           # Or you can use generic sub comparing 2 values 
      $equals = 0; 
      last; 
     } 
    } 
} 

पी.एस. मुझे यकीन नहीं है लेकिन List::Compare हमेशा सूचियों को सॉर्ट कर सकता है। मुझे यकीन नहीं है कि यह जोड़ों की तुलना कर सकता है।

+0

आप मेरे स्वाद के लिए बहुत ही उदारतापूर्वक 'स्केलर' तरीके का उपयोग कर रहे हैं। –

+0

स्केलर तुलना ऑपरेटर अपने तर्कों पर स्केलर संदर्भ लगाते हैं। तो, '@ ए == @ बी'' स्केलर (@ ए) == स्केलर (@ बी) 'और' $ i <@ ए' जैसा ही है 'i i scalar (@a) ' । –

+0

वह डेमो पठनीयता के लिए था ... मैं लगभग कभी भी उत्पादन कोड में स्केलर() का उपयोग नहीं करता, क्योंकि सिर्फ आपको यह पसंद नहीं आया। अगर आपको लगता है कि इससे ज्यादा मदद नहीं मिलती है, तो मैं इसे – DVK

1
my @a = qw' abc def efg ghy klm ghn '; 
my @b = qw' def ghy jgk lom com klm '; 

my $flag; 

foreach my $item(@a) { 
    $flag = @b~~$item ? 0 : 1; 
    last if !$flag; 
} 

ध्यान दें कि आप Perl 5.10, या बाद में की आवश्यकता होगी, smart match operator (~~) का उपयोग करें।

+0

माइक - यह पर्ल 5.10 से पहले काम करेगा? – DVK

+0

@ डीवीके, मुझे पता नहीं। मैंने इसे सीखना पर्ल से सीखा। मुझे 5.010; कथन का उपयोग करने की आवश्यकता नहीं है, लेकिन शायद यह केवल 5.5 के बाद काम करने योग्य है मैं इसे देख लूंगा। मैं अभी भी एक पर्ल सीखने वाला हूं। अगर कुछ गलत हो तो कृपया मुझे सही करें :) – Mike

+0

@ डीवीके, पुस्तक "पर्ल 5.10 का स्मार्ट मैच ऑपरेटर" कहती है। लेकिन ऐसा लगता है कि मैं डॉन ' टी का प्रयोग 5.010; कथन का उपयोग करना होगा। बस इसे फिर से परीक्षण किया गया है और 5.010 का उपयोग; कंसैक्स पर कम से कम ActivePerl 5.10.0 के साथ कथन अनावश्यक है। लेकिन मुझे लगता है कि यह काम नहीं करेगा पर्ल 5.10 से पहले। – Mike

1

आवश्यकता है कि 'अगर किसी भी तत्व मैचों', सेट के चौराहे का उपयोग से:

sub set{ 
    my %set = map { $_, undef }, @_; 
    return sort keys %set; 
} 
sub compare{ 
    my ($listA,$listB) = @_; 
    return ((set(@$listA)-set(@$listB)) > 0) 
} 
+0

इस प्रश्न को "perl" टैग किया गया है। मैं आपको पहली बार चेतावनी के बिना डाउनवोट नहीं करना चाहता ... –

+0

कोई सवाल पूरी तरह से भाषा-विशिष्ट नहीं है। मुझे यकीन है कि कोई इसका एक पर्ल संस्करण के साथ आ सकता है। यह सामान्य बिंदु को भी दिखाता है। –

+3

हां, लेकिन अगर कोई नौसिखिया आपका जवाब देखता है, तो इस पर्ची-टैग किए गए थ्रेड में, बिना किसी अधिसूचना के कि यह एक पर्ल उत्तर नहीं है, और इसे टाइप करता है, तो आश्चर्य है कि यह क्यों काम नहीं करता है? इस जवाब के साथ करने के लिए एकमात्र जिम्मेदार चीज इसे कम करना है। माफ़ कीजिये। –

2

यह एक तरीका है:

use warnings; 
use strict; 
my @a = split /,/, "abc,def,efg,ghy,klm,ghn"; 
my @b = split /,/, "def,ghy,jgk,lom,com,klm"; 
my $flag = 0; 
my %a; 
@a{@a} = (1) x @a; 
for (@b) { 
    if ($a{$_}) { 
     $flag = 1; 
     last; 
    } 
} 
print "$flag\n"; 
+0

सबसे आसान पढ़ा नहीं है लेकिन मुझे यह पसंद है। एक प्रश्न का उत्तर देते समय मुझे अधिक ऑफबीट व्यवहार की व्याख्या करना पसंद है, इसलिए हम कुकबुकिंग के बजाय सीखते हैं। – HerbN

+0

कोई व्यक्ति "@a {@a} = (1) x @a;" समझा सकता है? –

+0

यह '@ ए' के तत्वों के साथ'% a' की कुंजी को पॉप्युलेट करता है, और मान सभी हैं 1. यह समान नाम, हैश स्लाइस और स्केलर संदर्भ में एक सरणी के साथ विभिन्न चर प्रकारों के पर्ल के भत्ते का शोषण करता है। हालांकि, यह कोड गैर-अद्वितीय मानों वाले सरणी की तुलना करने के लिए काम नहीं करेगा – beasy

0

ब्रूट बल छोटे के लिए चाल करना चाहिए n:

my $flag = 0; 
foreach my $i (@a) { 
    foreach my $k (@b) { 
     if ($i eq $k) { 
      $flag = 1; 
      last; 
     } 
    } 
} 

ला के लिए

my $flag = 0; 
my %aa  =(); 
    $aa{$_} = 1 foreach (@a); 
foreach my $i (@b) { 
    if ($aa{$i}) { 
     $flag = 1; 
     last; 
    } 
} 

कहाँ एक बड़ी n|@a| + |@b| > ~1000

4

चेक आइटम है एक दूसरे को काटना समारोह है, जो आइटम है कि दोनों सूचियों में मौजूद हैं की एक सूची प्रदान करेगा बनाने के लिए: rge n, एक हैश तालिका का उपयोग करें। फिर आपका वापसी मूल्य छेड़छाड़ की गई सूची में वस्तुओं की संख्या पर निर्भर है।

आप आसानी से वेब पर पर्ल के लिए छेड़छाड़ का सर्वोत्तम कार्यान्वयन कर सकते हैं। मुझे कुछ साल पहले इसकी तलाश याद है।

यहाँ मैं क्या मिला है:

 

my @array1 = (1, 2, 3); 
my @array2 = (2, 3, 4); 
my %original =(); 
my @isect =(); 

map { $original{$_} = 1 } @array1; 
@isect = grep { $original{$_} } @array2; 

0

IMHO, आप List::MoreUtils::pairwise उपयोग करना चाहिए। हालांकि, अगर किसी कारण से आप नहीं कर सकते हैं, तो निम्न उप प्रत्येक इंडेक्स के लिए 1 लौटाएगा जहां पहले सरणी में मान दूसरे सरणी में मान के बराबर होता है।आप जितनी चाहें उतनी विधि को सामान्यीकृत कर सकते हैं और यदि आप चाहें तो अपना खुद का तुलनित्र पास कर सकते हैं, लेकिन उस समय, बस List::MoreUtils इंस्टॉल करना आपके समय का अधिक उत्पादक उपयोग होगा।

use strict; use warnings; 

my @a = qw(abc def ghi jkl); 
my @b = qw(abc dgh dlkfj jkl kjj lkm); 
my $map = which_ones_equal(\@a, \@b); 

print join(', ', @$map), "\n"; 

sub which_ones_equal { 
    my ($x, $y, $compare) = @_; 
    my $last = $#$x > $#$y ? $#$x : $#$y; 
    no warnings 'uninitialized'; 
    return [ map { 0 + ($x->[$_] eq $y->[$_]) } $[ .. $last ]; 
} 
0

यह पर्ल है। 'स्पष्ट' समाधान:

my @a = qw"abc def efg ghy klm ghn"; 
my @b = qw"def ghy jgk lom com klm"; 
print "arrays equal\n" 
    if @a == @b and join("\0", @a) eq join("\0", @b); 

दिया "\ 0" @a में नहीं किया जा रहा।

लेकिन यह पुष्टि करने के लिए धन्यवाद कि आपके खुद को रोल करने से कोई अन्य सामान्य समाधान नहीं है।

0
my @a1 = qw|a b c d|; 
my @a2 = qw|b c d e|; 

for my $i (0..$#a1) { 
    say "element $i of array 1 was not found in array 2" 
     unless grep {$_ eq $a1[$i]} @a2 
} 
संबंधित मुद्दे

 संबंधित मुद्दे