मैं पर्ल में किसी सरणी से डुप्लिकेट आइटम कैसे निकालूं?


156

मेरे पास पर्ल में एक सरणी है:

my @my_array = ("one","two","three","two","three");

मैं सरणी से डुप्लिकेट कैसे निकालूं?

जवाबों:


168

आप कुछ ऐसा कर सकते हैं जैसा कि perlfaq4 में दिखाया गया है :

sub uniq {
    my %seen;
    grep !$seen{$_}++, @_;
}

my @array = qw(one two three two three);
my @filtered = uniq(@array);

print "@filtered\n";

आउटपुट:

one two three

यदि आप एक मॉड्यूल का उपयोग करना चाहते हैं, तो uniqफ़ंक्शन से प्रयास करेंList::MoreUtils


28
कृपया उदाहरणों में $ a या $ b का उपयोग न करें क्योंकि वे जादू के
ग्लोबल्स हैं

2
यह myइस दायरे में है, इसलिए यह ठीक है। कहा जा रहा है, संभवतः एक अधिक वर्णनात्मक चर नाम चुना जा सकता है।
१ient:

2
@ हांथीम हाँ, लेकिन अगर आप इस फंक्शन में छँटाई करना चाहते हैं तो यह ट्रम्प $::aऔर $::b, यह नहीं होगा?
Vol7ron

5
@BrianVandenberg 1987 की दुनिया में आपका स्वागत है - जब यह बनाया गया था - और पर्ल के लिए लगभग 100% बैकवर्ड कॉम्बेलिटी - तो इसे समाप्त नहीं किया जा सकता है।
szabgab

18
sub uniq { my %seen; grep !$seen{$_}++, @_ }यह एक बेहतर कार्यान्वयन है क्योंकि यह बिना किसी मूल्य के आदेश को संरक्षित करता है। या इससे भी बेहतर, सूची :: MoreUtils से एक का उपयोग करें।
ikeगगामी

120

पर्ल दस्तावेज़ीकरण FAQs का एक अच्छा संग्रह के साथ आता है। आपका प्रश्न अक्सर पूछा जाता है:

% perldoc -q duplicate

ऊपर दिए गए कमांड के आउटपुट से उत्तर, कॉपी और पेस्ट किया गया है:

/Usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod में मिला
 मैं सूची या सरणी से डुप्लिकेट तत्वों को कैसे निकाल सकता / सकती हूं?
   (ब्रायन डी फ़ो द्वारा योगदान दिया गया)

   एक हैश का उपयोग करें। जब आप "अद्वितीय" या "डुप्लिकेट" शब्द सोचते हैं, तो सोचें
   "हैश कीज़"।

   यदि आप तत्वों के आदेश की परवाह नहीं करते हैं, तो आप बस कर सकते हैं
   हैश बनाएँ तो चाबियाँ निकालें। यह महत्वपूर्ण नहीं है कि आप कैसे हैं
   उस हैश का निर्माण करें: अद्वितीय तत्वों को प्राप्त करने के लिए बस "कुंजी" का उपयोग करें।

       मेरा% हैश = नक्शा {$ _, 1} @ ऐरे;
       # या हैश स्लाइस: @ हश {@ हर्रे} = ();
       # या एक फॉर्च्यूनर: $ हैश {$ _} = 1 फॉर्च्यू (@ ऐरे);

       my @unique = चाबियाँ% हैश;

   यदि आप एक मॉड्यूल का उपयोग करना चाहते हैं, तो "यूनीक" फ़ंक्शन से प्रयास करें
   "सूची :: MoreUtils"। सूची के संदर्भ में यह अद्वितीय तत्वों को लौटाता है,
   सूची में उनके आदेश को संरक्षित करना। स्केलर के संदर्भ में, यह लौटाता है
   अद्वितीय तत्वों की संख्या।

       उपयोग सूची :: MoreUtils qw (uniq);

       my @unique = uniq (1, 2, 3, 4, 4, 5, 6, 5, 7); # 1,2,3,4,5,6,7
       मेरे $ अद्वितीय = यूनीक (1, 2, 3, 4, 4, 5, 6, 5, 7); # 7

   आप प्रत्येक तत्व के माध्यम से भी जा सकते हैं और जो आपने देखा है उसे छोड़ सकते हैं
   इससे पहले। ट्रैक रखने के लिए हैश का उपयोग करें। पहली बार लूप ए देखता है
   तत्व, उस तत्व की% सीन में कोई कुंजी नहीं है। "अगला" कथन बनाता है
   कुंजी और तुरंत इसके मूल्य का उपयोग करता है, जो "अपरिभाषित" है, इसलिए लूप
   "पुश" के लिए जारी है और उस कुंजी के लिए मूल्य बढ़ाता है। अगला
   जिस समय लूप उसी तत्व को देखता है, उसकी कुंजी हैश और में मौजूद होती है
   उस कुंजी का मान सत्य है (चूंकि यह 0 या "अपरिभाषित" नहीं है), इसलिए
   अगला स्काइप कि पुनरावृत्ति और लूप अगले तत्व पर जाता है।

       my @unique = ();
       मेरा% देखा = ();

       मेरे $ ग्यारह (@ ऐरे) पर पहुंचें
       {
         अगले अगर $ {$ हाथी} ++ देखा;
         पुश @ यूनीक, $ एलएम;
       }

   आप इसे संक्षिप्त रूप से एक grep का उपयोग करके लिख सकते हैं, जो ऐसा ही करता है
   चीज़।

       मेरा% देखा = ();
       my @unique = grep {! $ देखा गया {$ _} ++} @ ऐरे;


17
Mah azers में जॉन iz ने Mah rep की चोरी की!
ब्रायन डी फ़ोय

5
मुझे लगता है कि आपको प्रश्न को वास्तव में देखने के लिए बोनस अंक प्राप्त करने चाहिए।
ब्रैड गिल्बर्ट

2
मुझे यह पसंद है कि सबसे अच्छा उत्तर 95% कॉपी-पेस्ट और ओसी के 3 वाक्य हैं। पूरी तरह से स्पष्ट हो सके, यह है सबसे अच्छा जवाब; मुझे सिर्फ वह तथ्य मनोरंजक लगता है।
पार्थियन ने

70

सूची स्थापित करें :: CPAN से MoreUtils

फिर अपने कोड में:

use strict;
use warnings;
use List::MoreUtils qw(uniq);

my @dup_list = qw(1 1 1 2 3 4 4);

my @uniq_list = uniq(@dup_list);

4
तथ्य यह है कि सूची :: MoreUtils को बंडल नहीं किया गया है w / perl थोड़े इसे इस्तेमाल करने वाली परियोजनाओं की पोर्टेबिलिटी को नुकसान पहुंचाता है :( (मैं एक के लिए नहीं होगा)
yPhil

3
@ भाषा: कॉल के @dup_listअंदर होना चाहिए uniq, नहीं@dups
incutonez

@yassinphilip CPAN उन चीजों में से एक है जो पर्ल को उतना ही शक्तिशाली और महान बनाता है जितना वह हो सकता है। यदि आप अपनी परियोजनाओं को केवल कोर मॉड्यूल के आधार पर लिख रहे हैं, तो आप अपने कोड पर एक बड़ी सीमा लगा रहे हैं, साथ ही संभवतः लिखे गए कोड के साथ, जो कुछ मॉड्यूल केवल उनका उपयोग करने से बचने के लिए बहुत बेहतर करते हैं। इसके अलावा, कोर मॉड्यूल का उपयोग कुछ भी गारंटी नहीं देता है, क्योंकि विभिन्न पर्ल संस्करण वितरण से कोर मॉड्यूल जोड़ या हटा सकते हैं, इसलिए पोर्टेबिलिटी अभी भी उस पर निर्भर है।
फ्रांसिस्को जाराबोज़ो

24

ऐसा करने का मेरा सामान्य तरीका है:

my %unique = ();
foreach my $item (@myarray)
{
    $unique{$item} ++;
}
my @myuniquearray = keys %unique;

यदि आप हैश का उपयोग करते हैं और हैश में आइटम जोड़ते हैं। आपके पास यह जानने का भी बोनस है कि सूची में प्रत्येक आइटम कितनी बार दिखाई देता है।


2
यह मूल आदेश को संरक्षित न करने का नकारात्मक पक्ष है, यदि आपको इसकी आवश्यकता है।
नाथन फ़ेलमैन

लूप के बजाय स्लाइस का उपयोग करना बेहतर है foreach:@unique{@myarray}=()
ओथजॉब

8

चर @array डुप्लिकेट तत्वों के साथ सूची है

%seen=();
@unique = grep { ! $seen{$_} ++ } @array;

7

एक साधारण पर्ल एक लाइनर के साथ किया जा सकता है।

my @in=qw(1 3 4  6 2 4  3 2 6  3 2 3 4 4 3 2 5 5 32 3); #Sample data 
my @out=keys %{{ map{$_=>1}@in}}; # Perform PFM
print join ' ', sort{$a<=>$b} @out;# Print data back out sorted and in order.

PFM ब्लॉक ऐसा करता है:

@In में डेटा MAP में फीड किया जाता है। MAP एक अनाम हैश बनाता है। कीज़ को हैश से निकाला जाता है और @ आउट में फीड किया जाता है


4

वह आखिरी बहुत अच्छा था। मैं इसे थोड़ा ट्विक करूंगा:

my @arr;
my @uniqarr;

foreach my $var ( @arr ){
  if ( ! grep( /$var/, @uniqarr ) ){
     push( @uniqarr, $var );
  }
}

मुझे लगता है कि यह शायद ऐसा करने का सबसे पठनीय तरीका है।


4

विधि 1: एक हैश का उपयोग करें

लॉजिक: एक हैश में केवल अनूठी कुंजी हो सकती है, इसलिए सरणी पर पुनरावृति, उस हैश की कुंजी के रूप में तत्व रखते हुए, सरणी के प्रत्येक तत्व को कोई भी मान असाइन करें। हैश की वापसी कुंजी, अपने अद्वितीय सरणी।

my @unique = keys {map {$_ => 1} @array};

विधि 2: पुन: प्रयोज्य के लिए विधि 1 का विस्तार

यदि हम अपने कोड में कई बार इस कार्यक्षमता का उपयोग करने वाले हैं तो सबरूटीन बनाना बेहतर है।

sub get_unique {
    my %seen;
    grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);

विधि 3: मॉड्यूल का उपयोग करें List::MoreUtils

use List::MoreUtils qw(uniq);
my @unique = uniq(@array);

1

पिछले जवाब बहुत ज्यादा इस कार्य को पूरा करने के संभावित तरीकों को संक्षेप में प्रस्तुत करते हैं।

हालांकि, मैं उन लोगों के लिए एक संशोधन का सुझाव देता हूं जो डुप्लिकेट की गिनती के बारे में परवाह नहीं करते हैं, लेकिन आदेश के बारे में परवाह करते हैं

my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;

ध्यान दें कि पहले सुझाए गए grep !$seen{$_}++ ...वेतन वृद्धि $seen{$_}को नकारने से पहले, इसलिए वेतन वृद्धि होती है चाहे वह पहले से हो %seenया नहीं। हालांकि, ऊपर, शॉर्ट-सर्किट जब $record{$_}सच होता है, तो जो एक बार 'बंद' सुना जाता है उसे छोड़ देता है %record

आप इस हास्यास्पदता के लिए भी जा सकते हैं, जो ऑटिविसिफिकेशन और हैश कीज़ के अस्तित्व का लाभ उठाता है:

...
grep !(exists $record{$_} || undef $record{$_}), @record;

हालाँकि, इससे कुछ भ्रम हो सकता है।

और अगर आप न तो ऑर्डर या डुप्लिकेट गिनती के बारे में परवाह करते हैं, तो आप हैश स्लाइस और मेरे द्वारा बताए गए ट्रिक का उपयोग करके एक और हैक के लिए कर सकते हैं:

...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped

तुलना करने वालों के लिए: sub uniq{ my %seen; undef @seen{@_}; keys %seen; } नीट।
स्टीवेस्लिवा

0

यह कोशिश करो, लगता है कि uniq फ़ंक्शन को ठीक से काम करने के लिए एक क्रमबद्ध सूची की आवश्यकता है।

use strict;

# Helper function to remove duplicates in a list.
sub uniq {
  my %seen;
  grep !$seen{$_}++, @_;
}

my @teststrings = ("one", "two", "three", "one");

my @filtered = uniq @teststrings;
print "uniq: @filtered\n";
my @sorted = sort @teststrings;
print "sort: @sorted\n";
my @sortedfiltered = uniq sort @teststrings;
print "uniq sort : @sortedfiltered\n";

0

अद्वितीय हैश कुंजी की अवधारणा का उपयोग करना:

my @array  = ("a","b","c","b","a","d","c","a","d");
my %hash   = map { $_ => 1 } @array;
my @unique = keys %hash;
print "@unique","\n";

आउटपुट: acbd

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.