chen870647924 / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

Strings.count(String string, String substring) #877

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I would be nice to have a substring count method. It can implemented now with 
Splitter and Iterables:

int count(String a, String s) {
   return Iterables.size(Splitter.on(s).split(a)) - 1;
}

or using String.indexOf

int count(String a, String s) {
    int i = 0, count = 0;
    while((i = a.indexOf(s, i++)) != -1) {
        count++;
        i += s.length();
    }
    return count;
}

assert 0 == count("", "xx");
assert 1 == count("xx", "xx");
assert 1 == count("axx", "xx");
assert 1 == count("axxa", "xx");
assert 1 == count("xxa", "xx");
assert 0 == count("xaxa", "xx");
assert 3 == count("xxxxxx", "xx");
assert 3 == count("axxaxxaxxa", "xx");
assert 1 == count("xxx", "xx");

Original issue reported on code.google.com by thomas.a...@gmail.com on 20 Jan 2012 at 8:28

GoogleCodeExporter commented 9 years ago
There was some discussion of a countMatches method here:
https://groups.google.com/group/guava-discuss/browse_thread/thread/cea923625cf9e
db6

(The Splitter approach is neat.)

Original comment by cpov...@google.com on 20 Jan 2012 at 2:10

GoogleCodeExporter commented 9 years ago
Okay, the count method is quite limited. An Iterator of substring start indices 
could be more useful.

class IndexOfIterator extends AbstractIterator<Integer> {

   static Iterator<Integer> indexOf(String string, String substring) {
       return new IndexOfIterator(string, substring);
   }

   private int i = 0;
   private String a;
   private String s;

   IndexOfIterator(String a, String s) {
       this.a = a;
       this.s = s;
   }

   @Override protected Integer computeNext() {
       i = a.indexOf(s, i);
       if(i == -1) endOfData();
       int next = i;
       i += s.length();
       return next;
   }
}

For example the HostAndPort.fromString method:

int colonPos = hostPortString.indexOf(':');
if (colonPos >= 0 && hostPortString.indexOf(':', colonPos + 1) == -1) {
    // Exactly 1 colon.  Split into host:port.
    host = hostPortString.substring(0, colonPos);
    portString = hostPortString.substring(colonPos + 1);
} else {
    // 0 or 2+ colons.  Bare hostname or IPv6 literal.
    host = hostPortString;
    hasBracketlessColons = (colonPos >= 0);
}

could be rewritten as:

Iterator<Integer> indexOf = IndexOfIterator.indexOf(hostPortString, ":");
host = hostPortString;
if (indexOf.hasNext()) {
    int colonPos = indexOf.next();
    hasBracketlessColons = indexOf.hasNext();
    if (!hasBracketlessColons) {
       // Exactly 1 colon. Split into host:port.
       host = hostPortString.substring(0, colonPos);
       portString = hostPortString.substring(colonPos + 1);
    }
}

and count as Iterators.size(IndexOfIterator.indexOf("axx","xx")).

Original comment by thomas.a...@gmail.com on 21 Jan 2012 at 5:08

GoogleCodeExporter commented 9 years ago
Before doing anything we need to find evidence that this is actually a common 
need  -- common enough that the usual indexOf-loop pattern is a problem.

Original comment by kevinb@google.com on 30 Jan 2012 at 6:30

GoogleCodeExporter commented 9 years ago
That's obvious.

A more powerful/complex solution would be to iterate over the matches of a 
regular expression (like Matcher.find):

public static Iterator<Range> spans(String string, String regex)

I'm not sure if I would put any of the three approaches count, indexOf or span 
in Guava. 

Original comment by thomas.a...@gmail.com on 31 Jan 2012 at 7:20

GoogleCodeExporter commented 9 years ago

Original comment by fry@google.com on 16 Feb 2012 at 7:18

GoogleCodeExporter commented 9 years ago

Original comment by kevinb@google.com on 30 May 2012 at 7:43

GoogleCodeExporter commented 9 years ago

Original comment by kevinb@google.com on 22 Jun 2012 at 6:16

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:14

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:18

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:08