एक सूची Raku में समान तत्वों के सन्निहित अनुक्रमों का पता लगाना


9

मैं एक सूची में समान तत्वों (जैसे लंबाई 2) के सन्निहित दृश्यों को खोजना चाहता हूं

my @s = <1 1 0 2 0 2 1 2 2 2 4 4 3 3>;
say grep {$^a eq $^b}, @s;

# ==> ((1 1) (2 2) (4 4) (3 3))

यह कोड ठीक दिखता है, लेकिन जब अनुक्रम के बाद एक और 2 जोड़ा जाता है 2 2 2या जब एक 2 को इसमें से हटा दिया जाता है, तो यह कहता है कि इसे Too few positionals passed; expected 2 arguments but got 1कैसे ठीक किया जाए? कृपया ध्यान दें कि मैं उन्हें forलूप का उपयोग किए बिना ढूंढने की कोशिश कर रहा हूं , अर्थात मैं यथासंभव कार्यात्मक कोड का उपयोग करके उन्हें खोजने की कोशिश कर रहा हूं।

वैकल्पिक: बोल्ड प्रिंटेड सेक्शन में:

<1 1 0 2 0 2 1 २ २ २ 4 4 3 3>

के कई क्रम 2 2देखे जाते हैं। उन्हें कितनी बार देखा जाता है उन्हें कैसे प्रिंट करें? पसंद:

((1 1) (2 2) (2 2) (4 4) (3 3))

जवाबों:


9

आपके इनपुट में तत्वों की एक समान संख्या है:

say elems <1 1 0 2 0 2 1 2 2 2 4 4 3 3>; # 14

आपका grepब्लॉक हर बार दो तत्वों का उपभोग करता है:

{$^a eq $^b}

इसलिए यदि आप किसी ऐसे तत्व को जोड़ते या हटाते हैं तो आपको वह त्रुटि मिलेगी जो ब्लॉक को अंत में बचे एकल तत्व पर चलाने पर मिलती है।


आपकी समस्या को हल करने के कई तरीके हैं।

लेकिन आपने ओवरलैपिंग के लिए अनुमति देने के विकल्प के बारे में भी पूछा, उदाहरण के लिए, (2 2)अनुक्रम मिलने पर आपको दो उप-सूचियाँ मिलती हैं 2 2 2। और, एक समान नस में, आप संभवतः दो मैच देखना चाहते हैं, शून्य नहीं, जैसे इनपुट:

<1 2 2 3 3 4>

इसलिए मैं उन समाधानों पर ध्यान केंद्रित करूंगा जो उन मुद्दों से भी निपटते हैं।

अतिरिक्त मुद्दों से निपटने के लिए समाधान स्थान की संकीर्णता के बावजूद, कार्यात्मक रूप से समाधान व्यक्त करने के कई तरीके अभी भी हैं।


एक तरीका है कि सिर्फ तुम्हारा अंत करने के लिए थोड़ा और कोड जोड़ता है:

my @s = <1 1 0 2 0 2 1 2 2 2 4 4 3 3>;
say grep {$^a eq $^b}, @s .rotor( 2 => -1 ) .flat

.rotorविधि उप सूचियों, एक ही लंबाई के प्रत्येक की एक सूची में एक सूची बदल देता है। उदाहरण के लिए, say <1 2 3 4> .rotor: 2प्रदर्शित करता है ((1 2) (3 4))। यदि लंबाई तर्क एक जोड़ी है, तो कुंजी लंबाई है और अगली जोड़ी शुरू करने के लिए मूल्य एक ऑफसेट है। यदि ऑफसेट नकारात्मक है, तो आपको उप-सूची ओवरलैप मिलती है। इस प्रकार say <1 2 3 4> .rotor: 2 => -1प्रदर्शित करता है ((1 2) (2 3) (3 4))

.flatविधि "सपाट" अपने invocant। उदाहरण के लिए, say ((1,2),(2,3),(3,4)) .flatप्रदर्शित करता है (1 2 2 3 3 4)

उपरोक्त समाधान को लिखने के लिए एक और अधिक पठनीय तरीका यह होगा कि हम इसे छोड़ दें flatऔर उपयोग करें .[0]और .[1]उप-सूचियों में अनुक्रमित करें rotor:

say @s .rotor( 2 => -1 ) .grep: { .[0] eq .[1] }

किसी अन्य उप-सूची आकार के लिए सामान्यीकरण करने वाली एक और भिन्नता के लिए एलिजाबेथ मैटीजेंस की टिप्पणी भी देखें।


यदि आपको अधिक सामान्य कोडिंग पैटर्न की आवश्यकता है, तो आप कुछ ऐसा लिख ​​सकते हैं:

say @s .pairs .map: { .value xx 2 if .key < @s - 1 and [eq] @s[.key,.key+1] }

.pairsएक सूची पर विधि प्रत्येक जोड़ी अपनी invocant सूची में तत्वों में से प्रत्येक के लिए इसी जोड़ों की सूची, वापस आती है। .keyप्रत्येक जोड़ी के invocant सूची में तत्व के सूचकांक है, .valueतत्व का मूल्य है।

.value xx 2लिखा जा सकता था .value, .value। (देखें xx।)

@s - 1@sशून्य से 1 में तत्वों की संख्या है ।

[eq]में [eq] listएक है कमी


यदि आपको यह निर्धारित करने के लिए पाठ पैटर्न के मिलान की आवश्यकता है कि समतुल्य समान तत्वों का गठन करने से आप इनपुट सूची को एक स्ट्रिंग में परिवर्तित कर सकते हैं, तो इसके साथ मेल खाने वाली क्रिया विशेषणों का उपयोग करके, जो मैचों की एक सूची उत्पन्न करते हैं, फिर मैचों की परिणामी सूची से अपने इच्छित पर मैप करें। परिणाम। ओवरलैप के साथ मिलान करने के लिए (उदाहरण के लिए उपयोग 2 2 2में परिणाम :((2 2) (2 2)):ov

say @s .Str .match( / (.) ' ' $0 /, :ov ) .map: { .[0].Str xx 2 }

यह काफी ठीक काम करता है। जब मैं अनुक्रम जोड़ने के लिए 2 2 s जोड़ता हूं तो 2 2 2 2यह 3 (2 2)s प्रिंट करता है जो कि अपेक्षित है। उस विधि के बारे में कभी नहीं सुना, जो rotorमैंने शुरू में squishविधि के साथ की है और जाँच की है कि क्या इसमें विशेषताएँ या तर्क हैं @s.squish(:length 2, :multiple_instances yes)लेकिन इसमें ऐसी सुविधाएँ नहीं हैं और यह कार्य के लिए उपयुक्त नहीं था। की तुलना में squish, rotor काफी फिट लगता है। वास्तव में यह इस प्रकार के ऑपरेशन के लिए सबसे उपयुक्त भी हो सकता है।
लार्स मैल्मस्टीन

3
my $size = 2; say <1 1 0 2 0 2 1 2 2 2 4 4 3 3>.rotor( $size => -$size + 1).grep: { [eq] $_ }# (1 1) (2 2) (2 2) (4 4) (3 3)) आपको केवल $sizeअनुक्रमों की विभिन्न लंबाई के लिए समायोजित करने की आवश्यकता है ।
एलिजाबेथ मैटीजेन

फिर से @LarsMalmsteen। कृपया LMK करें अगर आपको लगता है rotorकि मैंने जो दो विकल्प जोड़े हैं, वे मेरे उत्तर को कमजोर या मजबूत कर रहे हैं।
raiph

rotorसमाधान का परिष्कृत संस्करण यानी say @s.rotor(2=>-1).grep:{.[0]eq.[1]}स्वागत योग्य है क्योंकि यह दोनों छोटे (3 से 5 चार्ट के आधार पर रिक्त स्थान की गणना कैसे की जाती है) और अभी भी सभ्य दिखता है। rotorविधि के बिना सामान्यीकृत संस्करण भी स्वागत योग्य हैं क्योंकि वे दिखाते हैं कि कैसे कुछ quirks पसंद करते हैं xxऔर :ovउपयोग किए जाते हैं। तो समस्या बहुत अच्छी तरह हल हो गई है :)
लार्स मैल्मस्टीन

5

TIMTOWDI!

यहाँ gather/ का उपयोग कर एक पुनरावृत्ति दृष्टिकोण है take

say gather for <1 1 0 2 0 2 1 2 2 2 4 4 3 3> { 
    state $last = ''; 
    take ($last, $_) if $last == $_; 
    $last = $_; 
};

# ((1 1) (2 2) (2 2) (4 4) (3 3))

जवाब के लिए धन्यवाद। जो अपने आप में काफी ठीक लग रहा है। इसका take ($last, $_)हिस्सा gather and takeयुगल के उपयोग पर एक सभ्य उदाहरण है ।
लार्स मैल्मस्टीन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.