5

カンマ区切りの単語の単一の文字列で特定の単語が最初に出現するように文字列をトリミングしようとしています。例えば:

deleteLastOccurrence("foo,bar,dog,cat,dog,bird","dog")

戻る必要があります

"foo,bar,dog"

私は以下を持っています、そしてそれは正しく働いていないようです:

public String deleteLastOccurrence(String original, String target){
    String[] arr = original.split(",");
    arr = Arrays.copyOfRange(arr, Arrays.asList(arr).indexOf(target), original.length()-1);
    path = StringUtils.join(pathArray,",");
}

より簡単な方法に関する提案はありますか?前もって感謝します...

4

7 に答える 7

7

正規表現置換を使用します。

public static String deleteLastOccurrence(String original, String target){
    return original.replaceAll("(,)?\\b" + target + "\\b.*", "$1" + target);
}

このコードは、ターゲットが元の単語の最初または最後の単語である場合にも機能します(したがって、\b「単語の境界」を意味する正規表現構文)

また、deleteAfterFirstOccurrence()現在の名前が誤解を招く可能性があるため、メソッドの名前をに変更します。「最後の出現」は、必要なものとは無関係です。

ここに少しテストがあります:

public static void main(String[] args) {
    // Test for target in middle:
    System.out.println(deleteLastOccurrence("foo,bar,dog,cat,dog,bird,dog", "dog"));
    // Test for target at start:
    System.out.println(deleteLastOccurrence("dog,bar,dog,cat,dog,bird,dog", "dog"));
    // Test for target at end:
    System.out.println(deleteLastOccurrence("foo,bar,cat,bird,dog", "dog"));
}

出力:

foo,bar,dog
dog
foo,bar,cat,bird,dog
于 2012-05-26T00:59:49.237 に答える
2

更新:質問を詳しく調べて、OPが望んでいた結果ではなく、メソッドの名前を書いたことに気づきました。したがって、最後の発生を取り除くだけで、その後はトリミングされません。しかたがない!:)

あなたのスタイルによっては、これが簡単だとは思わないかもしれません。しかし、それは楽しい問題でした。このコードはもう少し明確だと思います。

public class ReplaceLast {

public String deleteLastOccurrence(String fromThis, String word){
    int wordLength = word.length();
    if(fromThis.startsWith(word + ",")){
        return fromThis.substring(wordLength + 1);
    }
    if(fromThis.endsWith("," + word)){
        return fromThis.substring(0, fromThis.length() - wordLength - 1);
    }
    int index = fromThis.lastIndexOf("," + word + ",");
    if(index == -1){
        return fromThis;
    }
    return fromThis.substring(0, index) + fromThis.substring(index+word.length() + 1);
}
@Test
public void testNotThere() {
    String actual = deleteLastOccurrence("foo,bar,dog,cat,dog,bird","moose");
    assertEquals("foo,bar,dog,cat,dog,bird", actual);
}
@Test
public void testMiddle() {
    String actual = deleteLastOccurrence("foo,bar,dog,cat,dog,bird","dog");
    assertEquals("foo,bar,dog,cat,bird", actual);
}

@Test
public void testFirst() {
    String actual = deleteLastOccurrence("foo,bar,dog,cat,dog,bird","foo");
    assertEquals("bar,dog,cat,dog,bird", actual);
}

@Test
public void testLast() {
    String actual = deleteLastOccurrence("foo,bar,dog,cat,dog,bird","bird");
    assertEquals("foo,bar,dog,cat,dog", actual);
}

@Test
public void testSubword() {
    String actual = deleteLastOccurrence("foo,bar,dog,cat,dog,bird","bir");
    assertEquals("foo,bar,dog,cat,dog,bird", actual);
}
}
于 2012-05-26T01:19:35.480 に答える
1

deleteLastOccurrence特定の単語が最初に出現したときに文字列をトリミングする問題を解決しようとしましたが、 IMOの誤解を招くメソッドの元の名前()は気にしませんでした。

サブワードではなく単一の単語のみに一致する秘訣は、文の前後に2つのコンマを追加してから、コンマで単語をチェックすることです。

つまり 、存在",dog,"するかどうかがチェックされます",foo,bar,dog,cat,dog,bird,"

package gicappa;

public class So {
    public static String trimSentenceOnFirstOccurrenceOf(String sentence, String word) {
        if (word.isEmpty()) return sentence;

        if (!addCommasAround(sentence).contains(addCommasAround(word))) return sentence;

        return trimAddedCommasOf(substringOfSentenceUntilEndOfWord(addCommasAround(sentence), addCommasAround(word)));
    }

    public static String substringOfSentenceUntilEndOfWord(String string, String word) {
        return string.substring(0, string.indexOf(word) + word.length());
    }

    public static String trimAddedCommasOf(String string) {return string.substring(1,string.length()-1);}

    public static String addCommasAround(String s) {return "," + s + ","; }
}

そして、私がTDDに使用したテストが必要な場合は、次のようにします。

package gicappa;

import org.junit.Test;

import static gicappa.So.trimSentenceOnFirstOccurrenceOf;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;

public class SoTest {
    @Test
    public void it_returns_the_same_sentence_for_empty_word() {
        assertThat(trimSentenceOnFirstOccurrenceOf("foo,bar,dog,cat,dog,bird", ""), is(equalTo("foo,bar,dog,cat,dog,bird")));
    }

    @Test
    public void it_returns_the_same_sentence_for_not_contained_word() {
        assertThat(trimSentenceOnFirstOccurrenceOf("foo,bar,dog,cat,dog,bird", "s"), is(equalTo("foo,bar,dog,cat,dog,bird")));
    }

    @Test
    public void it_returns_the_first_word() {
        assertThat(trimSentenceOnFirstOccurrenceOf("foo,bar,dog,cat,dog,bird", "foo"), is(equalTo("foo")));
    }

    @Test
    public void it_returns_the_same_sentence_if_is_matched_the_last_word() {
        assertThat(trimSentenceOnFirstOccurrenceOf("foo,bar,dog,cat,dog,bird", "bird"), is(equalTo("foo,bar,dog,cat,dog,bird")));
    }

    @Test
    public void it_trims_after_the_end_of_the_first_matched_word() {
        assertThat(trimSentenceOnFirstOccurrenceOf("foo,bar,dog,cat,dog,bird", "dog"), is(equalTo("foo,bar,dog")));
    }

    @Test
    public void it_does_not_trim_for_a_subword_of_a_contained_word() {
        assertThat(trimSentenceOnFirstOccurrenceOf("foo,bar,dog,cat,dog,bird", "do"), is(equalTo("foo,bar,dog,cat,dog,bird")));
    }

    @Test
    public void it_does_not_trim_for_a_subword_of_an_already_contained_word() {
        assertThat(trimSentenceOnFirstOccurrenceOf("dog,foozzo,foo,cat,dog,bird", "foo"), is(equalTo("dog,foozzo,foo")));
    }
}

より多くのOOクラスのための言葉のリファクタリングも次のようになります。

package gicappa;

public class Sentence {
    private String s;

    public Sentence(String sentence) {
        this.s = sentence;
    }

    public String trimOnFirstOccurrenceOf(String word) {
        if (word.isEmpty() || csvSentenceContainsWord(word)) return s;

        return substringSentenceToEndOf(word);
    }

    private String substringSentenceToEndOf(String word) {
        return addCommasTo(s).substring(1, addCommasTo(s).indexOf(addCommasTo(word)) + addCommasTo(word).length()-1);
    }

    private boolean csvSentenceContainsWord(String word) {
        return !addCommasTo(s).contains(addCommasTo(word));
    }

    public static String addCommasTo(String s) {return "," + s + ",";}
}

次のような使用法で:

new Sentence("dog,foozzo,foo,cat,dog,bird").trimOnFirstOccurrenceOf("foo"), is(equalTo("dog,foozzo,foo"))
于 2012-05-26T20:06:55.120 に答える
0

gonzoc0ding、すべての応答を読んだ後、私見あなたのやり方は、このように修正する必要があることを除いて、より単純でクリーンです:

public String deleteLastOccurrence(String original, String target){
    String[] arr = original.split(",");
    arr = Arrays.copyOfRange(arr,0, Arrays.asList(arr).indexOf(target));
    path = StringUtils.join(arr,",");
}

しかし、多分私はあなたの要件を理解していません...

于 2012-05-26T20:28:29.960 に答える
0

これはどう:

public String deleteLastOccurrence(String original, String target){
    return original.replace("(^|,)" + target + "(,|$)", "");
}
于 2012-05-26T01:01:00.273 に答える
0

非正規表現バージョンでの試行は次のとおりです。

public String trimTo(String in, String matchNoCommas) {
   if (in.startsWith(matchNoCommas + ","))  // special check here...
      return matchNoCommas;
   int idx = in.indexOf("," + matchNoCommas+ ",");
   if (idx < 0)
      return in;
   return in.substring(0, idx + matchNoCommas.length()+1);
}

@Bohemianによる正規表現バージョンと同じ結果を提供します。どちらがより理解しやすいかについてのあなたの呼びかけ。

于 2012-05-26T01:18:00.583 に答える
0

多分私は間違っていますが、これはそうではありませんか?

public trimCommaSeparatedListToIncludeFirstOccurrenceOfWord(String listOfWords, String wordToMatch) {
    int startOfFirstOccurrenceOfWordToMatch = listOfWords.indexOf(wordToMatch);
    int endOfFirstOccurrenceOfWordToMatch = startOfFirstOccurrenceOfWordToMatch + wordToMatch.length() - 1;

    return listOfWords.substring(0, endOfFirstOccurrenceOfWordToMatch);
}

これはOPが望んでいたことではないかもしれませんが、OPが求めていたものだと思います。例:f("doggy,cat,bird", "dog")を返し"dog"ます。

フルワードマッチングについては、他の人が示唆しているように、私は吸盤を正規表現します。

于 2012-05-26T16:52:20.690 に答える