【问题标题】:String combinations with multi-character replacement (yield return alternative re-write for Java) [closed]具有多字符替换的字符串组合(为 Java 生成返回替代重写)[关闭]
【发布时间】:2018-08-28 12:23:52
【问题描述】:

还有另一个 Stack Overflow 帖子是为与车辆登记号相关的算法创建的...

根据输入的车牌(例如 ABC123)和列表 替换值(例如 1 替换为 I)。我需要得到所有可能 组合。

@ArturoMenchaca 的答案非常适合 C#,但我希望在 Java 中使用它,但鉴于“yield”不可用,我真的无法思考如何转换它。

你会如何把这段代码翻译成 Java?

public static IEnumerable<string> Combinations(string s, Dictionary<char, char> replacements)
{
    return Combinations(s, replacements, 0, string.Empty);
}

private static IEnumerable<string> Combinations(string original, Dictionary<char, char> replacements, int index, string current)
{
    if (index == original.Length) yield return current;
    else
    {
        foreach (var item in Combinations(original, replacements, index + 1, current + original[index]))
            yield return item;

        if (replacements.ContainsKey(original[index]))
            foreach (var item in Combinations(original, replacements, index + 1, current + replacements[original[index]]))
                yield return item;
    }
}

你会调用然后调用这样的方法..

Dictionary<char, char> dict = new Dictionary<char,char>();
dict['1'] = 'I';
dict['3'] = 'B';
dict['A'] = 'H';
dict['O'] = '0';
dict['0'] = 'O';

var combs = Combinations("ABC123", dict);

【问题讨论】:

  • 只要内存允许,您可以将返回类型替换为List&lt;string&gt;,并将每个yield 替换为list.Add()。

标签: java combinations


【解决方案1】:

Java 没有像 C# yield return 那样使用“推送”逻辑迭代值的功能。

Java 仅支持“拉”逻辑,使用 Enumeration、Iterator 或 Spliterator(Stream 使用什么)。

如果您有记忆,您当然可以将所有组合“推送”到ArrayList,然后从那里“拉取”值。将yield return 逻辑转换为list.add() 调用很容易,所以我假设您不希望这样。

IEnumerable 的 Java 等效项是 Iterable,因此您需要一个 Iterator 实现。

下面的代码将做到这一点。它基于my answer to another question,因此请阅读该答案以了解整体逻辑,但基本上,您的示例就像在这个锯齿状数组中生成字符组合:

{{'A', 'H'}, {'B'}, {'C'}, {'1', 'I'}, {'2'}, {'3', 'B'}}

在下面的代码中,该锯齿状数组是textChars 数组,但它没有使用char[],而是使用String,因为String 实际上只是一个只读的char[]。

public static Iterable<String> combinations(String text, String... replacements) {
    Map<Character, String> repl = new HashMap<>();
    for (String r : replacements)
        if (repl.putIfAbsent(r.charAt(0), r) != null)
            throw new IllegalArgumentException("Duplicate replacement: [" + repl.get(r.charAt(0)) + "] vs [" + r + "]");
    String[] textChars = new String[text.length()];
    long count = 1;
    for (int i = 0; i < textChars.length; i++) {
        textChars[i] = repl.getOrDefault(text.charAt(i), text.substring(i, i+1));
        count = Math.multiplyExact(count, textChars[i].length());
    }
    long comboCount = count;
    return () -> new Iterator<>() {
        private long combo = 0;
        @Override
        public boolean hasNext() {
            return (this.combo < comboCount);
        }
        @Override
        public String next() {
            if (this.combo >= comboCount)
                throw new NoSuchElementException();
            long c = this.combo++;
            char[] buf = new char[textChars.length];
            for (int i = buf.length - 1; i >= 0; i--) {
                buf[i] = textChars[i].charAt((int) (c % textChars[i].length()));
                c /= textChars[i].length();
            }
            return new String(buf);
        }
    };
}

测试

combinations("ABC123", "1I", "3B", "AH", "O0", "0O").forEach(System.out::println);

输出

ABC123
ABC12B
ABCI23
ABCI2B
HBC123
HBC12B
HBCI23
HBCI2B

【讨论】:

    猜你喜欢
    • 2016-08-22
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多