删除字符串中的最后一个匹

时间:2012-05-26 00:52:08

标签: java string

我正在尝试将一个字符串修剪为单个逗号分隔字符串中特定单词的第一个匹配项。 E.g:

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,",");
}

有关更简单方法的任何建议吗?提前谢谢......

7 个答案:

答案 0 :(得分: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

答案 1 :(得分: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);
}
}

答案 2 :(得分:1)

我试图解决在第一次出现特定单词时修剪字符串的问题,而我并不关心IMO误导的方法的原始名称(deleteLastOccurrence)。

为我匹配单个单词而不是子单词的技巧是在句子之前和之后添加两个逗号,然后用逗号检查单词。

即。我会针对",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"))

答案 3 :(得分:0)

这个怎么样:

public String deleteLastOccurrence(String original, String target){
    return original.replace("(^|,)" + target + "(,|$)", "");
}

答案 4 :(得分: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的正则表达式相同的结果。你的电话更容易理解。

答案 5 :(得分: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"

对于全字匹配,我会像其他人建议的那样使用吸盘。

答案 6 :(得分: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,",");
}

但也许我不明白你的要求......