2012-03-02 10 views
32

के अंदर एक स्ट्रिंग की घटनाओं की संख्या की गणना करना एक निश्चित स्ट्रिंग को बड़ी संख्या में कितनी बार प्रदर्शित करने का सबसे तेज़ तरीका है? मेरा सबसे अच्छा अनुमान है कि उस स्ट्रिंग के सभी उदाहरणों को कुछ भी नहीं, लंबाई के अंतर की गणना करना और सबस्ट्रिंग की लंबाई से विभाजित करना होगा, लेकिन यह अपेक्षाकृत धीमा लगता है, और मुझे बड़ी मात्रा में डेटा का विश्लेषण करने की आवश्यकता है।किसी अन्य (पर्ल)

+0

इस बाहर की जाँच करने के लिए ... हालांकि यह 1999 से है चाहता हूँ सकता है, और वहाँ बात की इस तरह करने के लिए सबसे अधिक संभावना अन्य तरीके हैं कुशलता से: http://www.perlmonks.org/?node=How%20can%20I%20count%20the%20number%20of%20occurrences%20of%20a%20substring%20within%20a%20string%3F – summea

+7

'perldoc -q गिनती ' – toolic

+2

क्या ये ओवरलैप हो सकते हैं? – tchrist

उत्तर

57

आप स्ट्रिंग को कैप्चर कर सकते हैं, फिर उन्हें गिनें। यह () साथ कब्जा करने के लिए एक सूची संदर्भ लगाने से किया जा सकता है:

my $x = "foo"; 
my $y = "foo foo foo bar"; 
my $c =() = $y =~ /$x/g; # $c is now 3 

तुम भी एक सरणी को पकड़ने और सरणी भरोसा कर सकते हैं। इसी सिद्धांत, अलग तकनीक:

my @c = $y =~ /$x/g; 
my $count = @c; 
+0

धन्यवाद! यह दूसरा समाधान की तरह है। – ronash

+2

@ronash यह वही समाधान है। एक अस्थायी चर का उपयोग करता है, दूसरा नहीं करता है। आप 'मेरी $ count = @c = $ y = ~/$ x/g' भी कर सकते हैं, लेकिन इसके बजाय आप केवल' @ c' को अनदेखा कर सकते हैं और '()' का उपयोग कर सकते हैं। यदि आप वास्तविक मैचों की परवाह नहीं करते हैं तो सबसे अच्छा कौन सा है। – TLP

+2

यह काम नहीं करता है अगर '$ x' में कुछ रेगेक्स वर्ण होते हैं, क्योंकि' $ x' को रेगेक्स के रूप में व्याख्या किया जाता है। इसे ठीक करने के लिए '\ Q' जोड़ें, उदाहरण के लिए। '/ \ क्यू $ एक्स/g'। अधिक जानकारी के लिए 'quotemeta' देखें। – tuomassalo

8

आप वैश्विक रेगेक्स का उपयोग कर सकते हैं। कुछ ऐसा:

my @matches = $bigstring =~ /($littlestring)/g; 
my $count = @matches; 
+0

यह सबसे सरल समाधान की तरह लगता है, इसलिए मुझे लगता है कि मैं इसका उपयोग करूंगा, जब तक कि कोई तेज़ न हो? धन्यवाद! – ronash

+0

मुझे रेगेक्स की गति के बारे में निश्चित नहीं है, लेकिन मुझे यकीन है कि मिलान करने वाले परिचालनों का उपयोग केवल प्रतिस्थापन से तेज है। और मैं ऐसे समाधान के बारे में नहीं सोच सकता जिसके पास रेगेक्स के साथ कुछ नहीं है (यह अन्यथा देखना बहुत दिलचस्प होगा!) – MattLBeck

14
my $string = "aaaabbabbba"; 
my @count = ($string =~ /a/g); 
print @count . "\n"; 

या

my $count = ($string =~ s/a/a/g); 
+0

धन्यवाद! क्या यह काम करेगा यदि एक से अधिक पत्र मांगा जाए? – ronash

+1

एर्म, हाँ ... यह एक नियमित अभिव्यक्ति है, आप किसी भी चीज़ से मेल खा सकते हैं। –

+0

आपके दूसरे समाधान पर, tr/a/a/g बेहतर समाधान नहीं होगा, क्योंकि आप चरित्र को स्वयं ही प्रतिस्थापित करते हैं और tr उस से तेज़ है? – nerdbeere

4

बस संपूर्णता के लिए आप बार-बार एक पाश में सूचकांक फ़ंक्शन को कॉल करें और हर समय भरोसा कर सकते हैं उस में सबस्ट्रिंग के सूचकांक लौटे स्ट्रिंग, और प्रारंभिक स्थिति बदलें। वह regexes का उपयोग करने से बच जाएगा, और मेरे परीक्षण में regex समाधान से थोड़ा तेज है।

मुझे लगता है कि यहाँ से करने के लिए एक उप अनुकूलित किया है: http://www.misc-perl-info.com/perl-index.html

sub occurrences { 

    my($x, $y) = @_; 

    my $pos = 0; 
    my $matches = 0; 

    while (1) { 
     $pos = index($y, $x, $pos); 
     last if($pos < 0); 
     $matches++; 
     $pos++; 
    } 

    return $matches; 
} 
संबंधित मुद्दे