【问题标题】:Nested For-Loops - Separating String Elements with Array Objects嵌套 For 循环 - 用数组对象分隔字符串元素
【发布时间】:2012-07-28 15:56:23
【问题描述】:

我有一个简单的问题,但最近让我发疯了。 我正在制作一个化学程序(更具体地说是 Android 应用程序),并且我有一种方法可以分离用户输入的元素。例如,如果有人在哪里输入“FeZnKPb”,它将被分成“Fe”、“Zn”、“K”和“Pb”。

为此,我使用了一些嵌套循环和变量来控制它。我在 Chem[] 数组中定义了所有元素。然后将分离的元素存储在一个名为 savedChem[] 的数组中。它基本上只是循环遍历所有元素常量(Chem[]),如果与输入匹配,则将这些元素的名称和公式复制到 savedChem[]。

这是我的代码:

public void separateElements(String Input)
{
    boolean found = false;
    int start = 0;
    int end = 2;
    int length = Input.length();

    while(length >= end)
    {
        for(int x = 0; x < numChemicals; x++)
        {
            if((end + 0) > length)
            {
                end += 5;
                break;
            }
            if(Input.substring(start, end).equals(Chem[x].getFormula()))
            {
                savedChem[numSaved].setName(Chem[x].getName());
                savedChem[numSaved].setFormula(Chem[x].getFormula());
                numSaved++;
                start += 2;
                end += 2;
                found = true;
            }
            else
            {
                found = false;
            }
        }
        if(!found)
        {
            start += 2;
            end += 2;
        }
    }
}

我的问题是它只适用于 2 字符元素,例如“Fe”或“Zn”。我希望它也能识别像“K”这样的其他人。 另一个问题是它有时会跳过一些其他元素。例如,如果我要输入“FeZnHg”,它会将它们分成“Fe”、“Zn”和“Hg”。但是,如果我以不同的顺序输入它们,例如“ZnFeHg”,由于某种原因,它只会检测到“Zn”和“Hg”,而不是“Fe”。

我还有什么其他方法可以解决这个问题以使其正常工作?

【问题讨论】:

  • 正确区分大小写是否是一种约束?即,水星会一直是 Hg,还是会显示为 HG?
  • 你试过一步步调试你的代码吗?还是使用正则表达式更好。
  • @NathanielFord 是的,永远都是这样。我有另一种纠正方法。
  • 你总是可以这样做: savedChem[] = separateElements(input).toArray(new ChemicalElement[0]);如果您想在使用返回某个值的方法时更新 savedChem 数组。 (让 separateElements 方法返回一个值将使以后的测试更容易......)。

标签: java arrays if-statement for-loop


【解决方案1】:
  1. 不要预定义结尾,而是设置结尾start + length of chemical name being tested。所以你会比较Chem[x].getFormula().equals(Input.substring(start, start + Chem[x].getFormula().length())),然后你会提前startChem[x].getFormula().length()。我认为您还需要验证 start + Chem[x].getFormula().length() 是否小于总长度,否则您将获得字符串索引超出范围异常。
  2. 当您发现化学名称匹配时,您需要从内部循环中检查化学名称 break,否则您会继续与后面的名称进行比较,最终可能会得到 found=false。因此,您的底部 if 语句错误地前进了两个字符。例如,如果Fe 在您的列表中出现在Zn 之前,则它在找到Zn 之后将找不到Fe 并会跳过它。

【讨论】:

    【解决方案2】:

    鉴于元素总是一个大写字符和一个或两个小写字符(只有在一些非常短暂的元素的情况下才两个),您可以使用带有一些前瞻的正则表达式将您的输入拆分为短字符串。

    您可以使用 split 方法和一些前瞻方法将字符串拆分为元素字符串。考虑到 Nathaniel Ford 的 cmets:

    public enum ChemicalElement {
        F, Fe, Zn, K, Pb, Umm, //and so on...
    }
    
    public List<ChemicalElement> separateElements(String input) {
        String[] inputParts = input.split("(?=[A-Z]{1,1}[a-z]{0,2})");
    
        List<ChemicalElement> elementList = new LinkedList<ChemicalElement>();
        for (int i = 1; i < inputParts.length; i++) {
            String inputPart = inputParts[i];
    
            // note: throws IllegalArgumentException for unknown elements
            ChemicalElement element = ChemicalElement.valueOf(inputPart);
            if (null != element) {
                elementList.add(element);
            }
    
        }
        return elementList;
    }
    

    所以像这样的测试输入:

    String input = "FeZnKPbUmmK";
    List<ChemicalElement> elements = this.separateElements(input);
    

    将为您提供以下列表:

    [Fe、Zn、K、Pb、Umm、K]

    【讨论】:

    • 我同意这个解决方案,假设字符串是大写字母分隔的。我可能还建议将您的化学元素放入枚举中并在其中封装比较代码,以便您的函数可以返回 Set&lt;ChemicalElement&gt; 而不是修改数组实例成员。 (这不是你真正想要的)。
    • @NathanielFord 好吧,由于其他原因,我实际上希望它修改数组实例成员,因为我还将使用它的其他值。这是该方法无效的部分原因。不过,我会尝试 Mason 的建议,看看是否可行。
    • 谢谢,梅森!稍作修改后,您的解决方案运行良好。
    • @Pkmmte 如果调用方法需要修改实例成员,那么您应该在返回的集合中进行;这将使测试变得容易得多。此外,您可能不想使用数组 ([]),而是使用 List 或 Set;使用这些将允许您更多地利用面向对象。
    • for (int i = 1; i
    【解决方案3】:

    这是我的谦虚建议...对于您的程序的未来,我想在您有多个 O 原子的情况下它也会更好...如果无论如何都需要...我会做什么...我将创建一个所谓的 2d 矩阵(使用更多的内存但更少的计算能力)26x26,其中每个索引对应一个字母......所以我们知道元素符号是唯一的,最多 2 个字母(我不确定那些实验性的...对不起:D)...然后您将一一扫描字符串...假设您遇到 F 和 e ..这会自动建议二维矩阵的索引...因此您将查看该索引的内部。 ..如果它已满(通过某个符号),那么您会将 Fe 添加到您的一般列表中...但是让我们说在 F 之后您看到了一个 K...然后当您查看矩阵时,您会看到它是空的,您将得出结论是氟...无论如何,正如我所说的更多内存空间更少计算...您的选择

    【讨论】:

      猜你喜欢
      • 2012-01-23
      • 2013-04-05
      • 1970-01-01
      • 2012-04-19
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      相关资源
      最近更新 更多