【问题标题】:Concatenating strings to "sets" in Java在 Java 中将字符串连接到“集合”
【发布时间】:2010-08-10 16:58:35
【问题描述】:

实际上,不知道如何措辞这个算法问题。我在一个 android 应用程序中有切换按钮,每个按钮对应一个编号的频道。通道是 (1,n),但切换按钮 ID 是一些未知的、无序的(对按钮而言)整数。我需要收集频道号并构建一个命令字符串。我 1995 年的 Java 技能给了我这个:

String ch;
int i = 1;
for (ToggleButton toggle : toggles) {
    if (toggle.isChecked()) {
        ch = String.format("+%d", i+1);
        channels = channels.concat(ch);
    }
} 

如果选中切换按钮 1,2,4,5,6,7,11,13,21,22,23,24,25,则此代码 sn-p 成功地给了我字符串 "+1+2+4+5+6+7+11+13+21+22+23+24+25"

但是,我更想做的是字符串"+1/2, +4/7, +11, +13, +21/25"

我想知道是否有比多个 if 语句更简单的方法:

String ch;
int it = 0;
int last = 1;
for (ToggleButton toggle : toggles ) {
    if (toggle.isChecked()) {
    if (it == last + 1) {
            // somehow continue or note that we're only adding the "/"
        } else {
            // If we're not the next one, then build the last string
            // of "n/last" and then add ", +" to start building next string
        }
    }
    last++;
}

这似乎是一种蛮力类型的算法,所以我不知道 Java 是否有更优雅的解决方案(或者,更可能的是,应该有)

谢谢。

【问题讨论】:

  • 我认为您的意思是 1-2、4-7,...您还说 22/25,我认为您的意思是 21-25。有足够的歧义,我害怕更改你的帖子,以防我猜错了。
  • 比尔,谢谢。 21/25 是正确的。但是,我实际上确实是指 1/2、4/7。但是,由于“/”和“-”一样只是一个字符串,所以这并不重要。这是我正在使用的一个奇怪的 telnet 命令集,多个通道的命令出于某种原因使用了斜线。
  • 我的意思是,在这里提出问题时更直观。您可以事后进行翻译 - 或者在我的解决方案中实例化帮助程序类时将分隔符作为参数传递给构造函数:)

标签: java android string


【解决方案1】:

开启java.util.BitSet

我将java.util.BitSet 用于表示和跨度搜索算法。这是基本思想(see on ideone.com):

    import java.util.*;
    //...

    BitSet bs = new BitSet();
    int[] onBits = new int[] { 1,2,4,5,6,7,11,13,21,22,23,24,25 };
    for (int onBit : onBits) {
        bs.set(onBit);
    }
    System.out.println(bs);
    // {1, 2, 4, 5, 6, 7, 11, 13, 21, 22, 23, 24, 25}

    StringBuilder sb = new StringBuilder();
    for (int begin, end = -1; (begin = bs.nextSetBit(end + 1)) != -1; ) {
        end = bs.nextClearBit(begin) - 1;
        if (sb.length() > 0) sb.append(", ");
        sb.append(
            (begin == end)
                ? String.format("+%d", begin)
                : String.format("+%d/%d", begin, end)
        );
    }
    System.out.println(sb);
    // +1/2, +4/7, +11, +13, +21/25

nextSetBitnextClearBit 方法在查找跨度方面非常方便。


打开 StringBuilder 而不是 String+=/concat

StringBuilder 加入算法是一种标准算法。这是重构时的样子:

    StringBuilder sb = new StringBuilder();
    for (Element e : elements) {
        if (sb.length() > 0) sb.append(SEPARATOR);
        sb.append(e);
    }

您应该使用StringBuilderStringBuffer 而不是String+=/concat 来构建长字符串。

【讨论】:

  • 顺便说一下,BitSet 有一个flip/"toggle" 方法,以及or(联合)和and(交集)等类似集合的操作。
  • 你应该使用 StringBuffer 只有在你需要线程安全或者你的目标是不支持它的 Java 版本(pre-1.5 或 MIDP 的某些版本)。
  • 使用 StringBuilder 时,必须先初始化容量,否则与 String "+" concat 相比,这里没有任何性能。
【解决方案2】:

你的行不通,有一个最终问题,你必须复制代码以在范围结束后清理(在你的数据集上尝试)

我知道您正在寻找简短/简洁的内容,但我更喜欢通过执行以下操作使 业务逻辑代码更短、更简洁:

Counter counter=new Counter();

for(int i=1;i<=toggles.length;i++)
    if(toggles.get(i).isChecked())
        counter.append(i);

System.out.println(counter.getResult());

这样您的代码部分会更短,但您需要一个新类。这个类是可重用的,任何时候你想重新创建相同类型的范围列表,你都明白了!这两段代码应该更容易理解,因为每一段都只是在做自己的工作。它有点长,但老实说,我不喜欢任何形式的简洁,形状或形式。只要你是 DRY,越明确越好。

PS。我今天要不戴支架了。

所以:

public class counter
    int a=-1;
    int b=-1;
    String result="";

    public append(int i)
        if(a == -1)
            a=i;
            b=i;
        else if(b == i-1)
            b++;
        else
            finished();

    public finished()
        if(result.length != 0 && a != -1)
            result+="+";
        if(a != -1)
            result.append(a);
            if(a != b)
                result.append("/"+b);
        a=-1;
        b=-1;

    public String getResult()
        finished();
        return result;

【讨论】:

  • 这有一些错误,可能仍然存在。请务必回来查看 - 我现在至少更新了 3 次,但我认为它现在可以工作了。
猜你喜欢
  • 2014-10-25
  • 1970-01-01
  • 1970-01-01
  • 2011-07-22
  • 2016-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-02
相关资源
最近更新 更多