1

n 単語の後に文字列を切り捨てるルーチンを持つライブラリはありますか? 私は回すことができるものを探しています:

truncateAfterWords(3, "hello, this\nis a long sentence");

の中へ

"hello, this\nis"

自分で書くこともできましたが、このようなものはオープンソースの文字列操作ライブラリに既に存在するのではないかと考えました。


以下は、すべてのソリューションが合格すると予想されるテスト ケースの完全なリストです。

import java.util.regex.*;

public class Test {

    private static final TestCase[] TEST_CASES = new TestCase[]{
        new TestCase(5, null, null),
        new TestCase(5, "", ""),
        new TestCase(5, "single", "single"),
        new TestCase(1, "single", "single"),
        new TestCase(0, "single", ""),
        new TestCase(2, "two words", "two words"),
        new TestCase(1, "two words", "two"),
        new TestCase(0, "two words", ""),
        new TestCase(2, "line\nbreak", "line\nbreak"),
        new TestCase(1, "line\nbreak", "line"),
        new TestCase(2, "multiple  spaces", "multiple  spaces"),
        new TestCase(1, "multiple  spaces", "multiple"),
        new TestCase(3, " starts with space", " starts with space"),
        new TestCase(2, " starts with space", " starts with"),
        new TestCase(10, "A full sentence, with puncutation.", "A full sentence, with puncutation."),
        new TestCase(4, "A full sentence, with puncutation.", "A full sentence, with"),
        new TestCase(50, "Testing a very long number of words in the testcase to see if the solution performs well in such a situation.  Some solutions don't do well with lots of input.", "Testing a very long number of words in the testcase to see if the solution performs well in such a situation.  Some solutions don't do well with lots of input."),
    };

    public static void main(String[] args){
        for (TestCase t: TEST_CASES){
            try {
                String r = truncateAfterWords(t.n, t.s);
                if (!t.equals(r)){
                    System.out.println(t.toString(r));
                }
            } catch (Exception x){
                System.out.println(t.toString(x));
            }       
        }   
    }

    public static String truncateAfterWords(int n, String s) {
        // TODO: implementation
        return null;
    }
}


class TestCase {
    public int n;
    public String s;
    public String e;

    public TestCase(int n, String s, String e){
        this.n=n;
        this.s=s;
        this.e=e;
    }

    public String toString(){
        return "truncateAfterWords(" + n + ", " + toJavaString(s) + ")\n  expected: " + toJavaString(e);
    }

    public String toString(String r){
        return this + "\n  actual:   " + toJavaString(r) + "";
    }

    public String toString(Exception x){
        return this + "\n  exception: " + x.getMessage();
    }    

    public boolean equals(String r){
        if (e == null && r == null) return true;
        if (e == null) return false;
        return e.equals(r);
    }   

    public static final String escape(String s){
        if (s == null) return null;
        s = s.replaceAll("\\\\","\\\\\\\\");
        s = s.replaceAll("\n","\\\\n");
        s = s.replaceAll("\r","\\\\r");
        s = s.replaceAll("\"","\\\\\"");
        return s;
    }

    private static String toJavaString(String s){
        if (s == null) return "null";
        return " \"" + escape(s) + "\"";
    }
}

このサイトには、他の言語でこれに対する解決策があります。

4

4 に答える 4

4

シンプルな正規表現ベースのソリューションを使用できます。

private String truncateAfterWords(int n, String str) {
   return str.replaceAll("^((?:\\W*\\w+){" + n + "}).*$", "$1");    
}

ライブデモ: http://ideone.com/Nsojc7

更新:パフォーマンスの問題を解決するためのコメントに基づいて:

大量の単語を処理する際にパフォーマンスを高速化するには、次の方法を使用します。

private final static Pattern WB_PATTERN = Pattern.compile("(?<=\\w)\\b");

private String truncateAfterWords(int n, String s) {
   if (s == null) return null;
   if (n <= 0) return "";
   Matcher m = WB_PATTERN.matcher(s);
   for (int i=0; i<n && m.find(); i++);
   if (m.hitEnd())
      return s;
   else
      return s.substring(0, m.end());
}
于 2013-04-11T18:03:27.933 に答える
0

これは、正規表現を使用して、十分な単語になるまでループ内の次のスペースのセットを見つけるバージョンです。BreakIterator ソリューションに似ていますが、正規表現を使用して単語の区切りを反復処理します。

// Any number of white space or the end of the input
private final static Pattern SPACES_PATTERN = Pattern.compile("\\s+|\\z");

private static String truncateAfterWords(int n, String s) {
    if (s == null) return null;
    Matcher matcher = SPACES_PATTERN.matcher(s);
    int matchStartIndex = 0, matchEndIndex = 0, wordsFound = 0;
    // Keep matching until enough words are found, 
    // reached the end of the string, 
    // or no more matches
    while (wordsFound<n && matchEndIndex<s.length() && matcher.find(matchEndIndex)){
        // Keep track of both the start and end of each match
        matchStartIndex = matcher.start();
        matchEndIndex = matchStartIndex + matcher.group().length();
        // Only increment words found when not at the beginning of the string
        if (matchStartIndex != 0) wordsFound++;
    }
    // From the beginning of the string to the start of the final match
    return s.substring(0, matchStartIndex);
}
于 2013-04-17T00:07:00.730 に答える