【问题标题】:String Array's in Java and parsing themJava中的字符串数组并解析它们
【发布时间】:2013-10-26 02:50:39
【问题描述】:

好的,所以我有两个字符串。第一个字符串是一个单词,第二个字符串是一个句子。现在句子包含了这个词,也包含了这个词的定义。请参阅下面的示例。

字串:AED 句子字符串:这很像“Kindle”或自动体外除颤器 (AED)。

所以我需要找到定义:自动体外除颤器这个词:AED。

我需要做的是解析并找到定义。我目前陷入困境,我需要一些帮助。下面的逻辑将单词分解为数组,将句子分解为数组。不幸的是,这并不完整。而且,当逻辑查看单词的第一个字母时,它不会真正起作用,因为 AED 中的 A 是大写字母,而自动中的 a 是小写字母。

private void getDefinitions(String word, String sentence) {
    if (sentence.contains(word)) {
        String[] wordStrAry = word.split("");
        String[] sentStr = sentence.split(" ");
        for (int sentInt = 0; sentInt < sentStr.length; sentInt++){
            for (int wordInt = 0; wordInt < wordStrAry.length; wordInt++) {
            wordStrAry[wordInt].trim();
                if (!wordStrAry[wordInt].equals("")) {
                    if (sentStr[sentInt].startsWith(wordStrAry[wordInt])){
                        System.out.println(sentStr[sentInt]);
                    }
                }
            }
        }
    }
}

我忘记了一点信息是我需要从句子中提取定义并将其显示在文本框中。

【问题讨论】:

  • 那么,你想在一个句子中找到任何首字母缩写词或首字母缩写词,然后在句子中查找它们代表什么?
  • 使用此代码,您可以获得任意首字母缩写词。如果您保留一些character 将您的word 与您的句子中的含义联系起来会更好,这样您就可以不用做那么多比较..
  • 当您收到“Word String : AED Sentence String : 这很像“Kindle”或自动体外除颤器 (AED) 等电子设备时会发生什么?
  • 自动体外除颤器

标签: java string


【解决方案1】:
public static String getDefinition(String acronym, String sentence) {
    if (!sentence.toLowerCase().contains(acronym.toLowerCase())) {
        return null;
    }

    StringBuilder patternBuilder = new StringBuilder();
    for (char letter : acronym.toCharArray()) {
        patternBuilder.append("[");
        patternBuilder.append(Character.toLowerCase(letter));
        patternBuilder.append(Character.toUpperCase(letter));
        patternBuilder.append("]");
        patternBuilder.append("\\w*\\s+");
    }
    patternBuilder.delete(patternBuilder.length() - 3, patternBuilder.length());

    Pattern pattern = Pattern.compile(patternBuilder.toString());
    Matcher matcher = pattern.matcher(sentence);
    if (!matcher.find()) {
        return null;
    }

    return matcher.group();
}

public static void main(String[] args) {
    String acronym = "AED";
    String sentence = "This will be much like the \"Kindle\" or Automated External Defibrillator (AED)";
    String definition = getDefinition(acronym, sentence);
    if (definition != null) {
        System.out.println(acronym + " = " + definition);
    } else {
        System.out.println("There is no definition for " + acronym);
    }
}

【讨论】:

  • 我想这可能就是我想要的。我不得不使用 RegEx 来获得原始的 Acronym。让我看看。
  • 我试过了,它返回小写字母。我需要返回原始字符串的方法。
  • 修改了代码,现在它返回原始字符串,而不是小写。
  • MateuszB 如果你能联系我,我有一个问题要问你。
【解决方案2】:

为什么要把它分解成一个数组?

您可以只使用字符串contains 方法

sentence.contains(word)

如果返回 true,它确实包含它。请注意,这是区分大小写的。如果您希望它不区分大小写,那么您可能想要这样做

sentence.toLowerCase().contains(word.toLowerCase())

【讨论】:

  • 他已经这样做了(第一行)。但是我不知道他为什么需要下面的代码……
  • 很酷,如果找到了,那又如何。我需要从句子中提取定义。这就是为什么我把它放到一个数组中。如果您有更好的想法,那就太好了。
  • 看看我需要的是从句子中提取定义并将其显示在文本框中。
  • 如果句子包含 AED,那么您知道它存在,所以您可以在文本框中填充 AED,您不能吗?你不需要再次解析句子
  • 我已经将 AED 从句子中删除,但我还需要从句子中删除“自动体外除颤器”的定义。所以我问我该怎么做。
【解决方案3】:

如果我对您的理解正确,这将搜索您在您指定的句子中指定的首字母缩写词,然后找到与该首字母缩写词匹配的短语并返回它们。请注意,如果有多种可能性并且错误的可能性出现在正确的可能性之前,这将失败。我只是想不出一种方法来避免这种情况(尽管您可以通过找出更接近首字母缩写词出现的位置来减少它)。

public static String makeInitialism(String[] words)
{
    StringBuilder initialism = new StringBuilder();
    for(String word : words)
    {
        initialism.append(word.toUpperCase().charAt(0));
    }
    return initialism.toString();
}

public static String buildPhrase(String[] words)
{
    StringBuilder phrase = new StringBuilder();
    for(int i = 0; i < words.length; i++)
    {
        phrase.append(words[i].toUpperCase().charAt(0));
        if(words[i].length() > 1)
        {
            phrase.append(words[i].substring(1));
        }
        if((i + 1) < words.length)
        {
            phrase.append(" ");
        }
    }
    return phrase.toString();
}

public static String getDefinition(String word, String sentence) throws DefinitionNotFoundException
{
    //StackOverflow removes double spaces, you can replace " "+" " with a double space in your code.
    sentence = sentence.replace(" "+" ", " ");
    String[] words = sentence.split(" ");
    int wordsToJoin = word.length();
    word = word.toUpperCase();
    for(int i = 0; i < words.length - (wordsToJoin - 1); i++)
    {
        String[] tryingWords = Arrays.copyOfRange(words, i, i + wordsToJoin);
        if(word.equals(makeInitialism(tryingWords)))
        {
            return word + ": " + buildPhrase(tryingWords);
        }
    }
    throw new DefinitionNotFoundException();
}

跑步:

System.out.println(getDefinition("LVPD", "I have a good friend at the Las Vegas police department"));

产生输出:

LVPD: Las Vegas Police Department

【讨论】:

  • 好的,但我需要以原始形式返回句子中的定义,而不是小写形式。
  • 返回的定义始终与文本中显示的完全相同。如果它显示小写,那是因为您使用了一个定义为小写的句子。我的例子是混合大小写来表明这一点。
  • 如果你想改变定义的大小写,你总是可以用phrase.append(words[i].toUpperCase().charAt(0)); if(words[i].length() &gt; 1) phrase.append(words[i].substring(1));替换phrase.append(words[i]);
  • 我的数组超出了 initialism.append(word.toUpperCase().charAt(0));
  • 事实上,异常是 StringIndexOutOfBoundsException,我想不出任何给出 ArrayIndexOutOfBoundsException 的东西。
【解决方案4】:
package acronym;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Acronym {

    // any sequence of "word character"(\w) between "word boundaries" (\b) that starts with two to-be-defined characters (%c) - String.format(...)
    private static final String aWordPatternFormat = "\\b[%c%c]\\w*\\b";

    public Acronym() {
        super();
    }

    public String getDefinition(String word, String sentence) {

        String regex = buildRegex(word);

        return findDefinition(regex, sentence);
    }

    private String buildRegex(String word) {

        StringBuilder builder = new StringBuilder();

        builder.append("(");

        for (int i = 0; i < word.length(); i++) {

            char ch = word.charAt(i);

            String aWordPatternRegex = String.format(aWordPatternFormat, Character.toUpperCase(ch), Character.toLowerCase(ch));

            // ignore any spaces before the first word
            if(i != 0) {
                builder.append("\\s");
            }

            // add the word regex to the phrase regex we are building
            builder.append(aWordPatternRegex);
        }

        builder.append(")");

        return builder.toString();
    }

    private String findDefinition(String regex, String sentence) {

        Pattern pattern = Pattern.compile(regex);

        Matcher matcher = pattern.matcher(sentence);

        boolean matches = matcher.find();

        if(!matches) {
            throw new RuntimeException("The sentence does not contains the definition of the word");
        }

        return matcher.group();
    }

}

--- JUnit 测试 ---

package acronym;

import static org.junit.Assert.assertEquals;

import org.junit.Test;


public class AcronymTest {

    @Test
    public void testGetDefinitions() {

        assertEquals("automated external defibrillator", new Acronym().getDefinition("AED", "This will be much like the “Kindle” or automated external defibrillator (AED)"));
        assertEquals("Las Vegas police department", new Acronym().getDefinition("LVPD", "I have a good friend at the Las Vegas police department shall"));
    }


}

【讨论】:

  • 其实这是迄今为止最好的解决方案。但我需要考虑带有特殊字符的单词 - 在它们之间是一个单词。我该怎么做。
  • 有点像 Save-On 应该被认为是一个词而不是两个
  • 您希望它如何工作?您希望如何考虑“Save-On”?一两个字?只需在上面添加一个失败的测试用例!
【解决方案5】:
package acronym;

public class Acronym {

    public String getDefinition(String word, String sentence) {
        sentence = sentence.trim();
        word = word.trim();

        final int sLength = sentence.length();
        final int wLength = word.length();

        int startPos = 0, endPos = sLength;
        int w = 0, s = 0;

        if(equalsIgnoringCase(sentence, s, word, w)) {
            startPos = s;
            w++; s++;
        }

        for (; s < sLength; s++) {
            if(sentence.charAt(s) == ' ') {
                if(w == 0) {
                    startPos = s + 1;
                }
                if(w == wLength) {
                    endPos = s;
                    break;
                }
                if(equalsIgnoringCase(sentence, s + 1, word, w)) {
                    w = (w < wLength) ? w + 1 : wLength;
                }
                else {
                    w = 0;
                }
            }
        }
        return sentence.substring(startPos, endPos);
    }

    private boolean equalsIgnoringCase(String sentence, int s, String word, int w) {
        return equalsIgnoringCase(sentence.charAt(s), word.charAt(w));
    }

    private boolean equalsIgnoringCase(char sCharAt, char wCharAt) {
        return Character.toLowerCase(sCharAt) == Character.toLowerCase(wCharAt);
    }

}

上一个示例的 JUnit 测试:

package acronym;

import static org.junit.Assert.assertEquals;

import org.junit.Test;


public class AcronymTest {

    @Test
    public void testGetDefinitions() {

        assertEquals("automated external defibrillator", new Acronym().getDefinition("AED", "This will be much like the “Kindle” or automated external defibrillator (AED)"));
        assertEquals("Las Vegas police department", new Acronym().getDefinition("LVPD", "I have a good friend at the Las Vegas police department shall"));
    }


}

【讨论】:

    【解决方案6】:
    public class AcronymSplit implements Acronym {
    
    public AcronymSplit() {
        super();
    }
    
    @Override
    public String getDefinition(String word, String sentence) {
        String[] split = sentence.replaceAll("[^A-Za-z\\s]", "").split("[^\\w]", -1);
    
        StringBuilder builder = new StringBuilder();
        for (String string : split) {
            builder.append(string.charAt(0));
        }
        int index = builder.toString().toLowerCase().indexOf(word.toLowerCase());
        builder = new StringBuilder();
        for (int i = index; i < (index + word.length()); i++) {
            if(i != index) {
                builder.append(' ');
            }
            builder.append(split[i]);
        }
        return builder.toString();
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2012-09-29
      • 2011-07-18
      • 1970-01-01
      • 2021-01-10
      • 2018-12-14
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多