通过Java中的外观命令字符串

时间:2011-07-04 09:43:28

标签: java algorithm string grouping

我有一个已根据数值排列的字符串列表。 现在我想按照以下方式对这些字符串进行分组。

假设我有一个如下所示的文本文件:

DBC
EB
CD
EDD
ACB
EBC
DAC
教育局
CDA

我希望以这样的方式订购它:

DBC
DAC
EB
EBC
EDD
教育局
CD
CDA
ACB

因此,您可以看到它必须按字符串的字母分组并将它们堆叠在一起。
什么是完成这项任务最有效的方法?

更新。 如您所见,所需的顺序不是按字母顺序排列的,包括反向顺序。正如我所提到的,目标是分组字符串并通过首次出现来对它们进行排序。对于这个例子,我使用字母来简化我想要解决的(很多)更复杂的问题。这里要集中注意力的是每个字符串的字母出现的顺序。按特定顺序分组,而不是订购。

4 个答案:

答案 0 :(得分:2)

您需要的是前缀树(trie)。这是一棵树,其中每个级别对应于字符串中的位置(root = 0,级别1 =第一个字母等),并且每个节点对应于一个字母。 该节点还包含一个布尔值(比如isWord),指定是否有一个单词在那里结束,在你的情况下你需要另一个int说index,以指定你的初始单词的索引排序(如果isWord == true)。

您也可以使用最初包含所有单词的Set。

现在只需开始遍历原始列表,对于未采取的每个单词,请执行以下操作:

  1. 在trie中找到它,将其添加到新列表中,将其标记为已拍摄。
  2. 取其子树中所有未被采用的单词(即所有以相同前缀开头的单词),按索引排序并将其标记为已添加到新列表中。
  3. 将一个级别向上移动到当前节点的父级,并执行相同的操作,直到到达根目录。
  4. 希望有所帮助。

答案 1 :(得分:1)

好的,这看起来很复杂。如果我理解这一点,你需要一个两步解决方案:

  1. 您需要将多个字符串映射到公共前缀

    public static String mapKey(String value){
        // or whatever your mapping to a common key would be
        return value.substring(0, 2);
    }
    
  2. 您需要按发生顺序按此前缀排序

    我建议你使用的是Guava Multimap,特别是LinkedHashMultimap

    Multimap<String, String> map = LinkedHashMultimap.create();
    // write data to map
    for(String word: yourData){
        map.put(mapKey(word), word);
    }
    // read items from map, grouped by prefix
    for (String value : map.values()) {
        System.out.println(value);
    }
    

    说明:LinkedHashMultimap按照创建密钥的顺序迭代其条目。由于您有多个具有公共密钥的条目(由mapKey定义),因此它们将作为组返回。

  3. 实际上,在重新阅读您的要求时,LinkedHashMultimap也不太合适(因为各个组的项目会随机出现)。您需要自定义Multimap

    Multimap<String,String> map = Multimaps.newListMultimap(
            new LinkedHashMap<String, Collection<String>>(),
            (Supplier<? extends List<String>>) new Supplier<List<String>>() {
        public List<String> get() {
            return new ArrayList<String>();
        }
    });
    

    (其余代码保持不变)

答案 2 :(得分:0)

保持广告订单顺序的trie,例如使用LinkedHashMap,就可以了。

我把这样一个简单的三重奏组合在一起:

import org.junit.Test;

import java.util.*;

import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;

public class LinkedTrieTest {

    @Test
    public void testLinkedTrie() {

        List<String> input = asList(
                "dbc",
                "eb",
                "cd",
                "edd",
                "acb",
                "ebc",
                "dac",
                "edb",
                "cda"
        );

        List<String> expected = asList(
                "dbc",
                "dac",
                "eb",
                "ebc",
                "edd",
                "edb",
                "cd",
                "cda",
                "acb"
        );

        assertEquals(expected, iterableToList(new LinkedTrie(input)));
    }

    private List<String> iterableToList(Iterable<String> t) {
        List<String> result = new ArrayList<String>();
        for (String s : t) {
            result.add(s);
        }
        return result;
    }

    private class LinkedTrie implements Iterable<String> {

        private Node root = new Node();

        private LinkedTrie() {
        }

        private LinkedTrie(Iterable<String> strings) {
            addAll(strings);
        }

        private void addAll(Iterable<String> strings) {
            for (String string : strings) {
                add(string);
            }
        }

        public void add(String s) {
            root.add(s);
        }

        @Override
        public Iterator<String> iterator() {
            return root.iterator();
        }

        private class Node {
            private Map<Character, Node> nodes = new LinkedHashMap<Character, Node>();

            private void add(String s) {
                if (s.isEmpty()) {
                    nodes.put(null,null);
                    return;
                }
                Character c = s.charAt(0);
                Node node = nodes.get(c);
                if (null == node) {
                    node = new Node();
                }
                nodes.put(c, node);
                node.add(s.substring(1));
            }

            private Iterator<String> iterator() {
                return new TrieIterator();
            }

            private class TrieIterator implements Iterator<String> {

                private Iterator<Map.Entry<Character,Node>> prefixesWithSuffixes = nodes.entrySet().iterator();
                private Character currentPrefix;
                private Iterator<String> suffixesForCurrentPrefix = Collections.<String>emptyList().iterator();

                @Override
                public boolean hasNext() {
                    return suffixesForCurrentPrefix.hasNext() || prefixesWithSuffixes.hasNext();
                }

                @Override
                public String next() {
                    if (outOfSuffixesForCurrentPrefix()) {
                        if (outOfPrefixes()) {
                            throw new NoSuchElementException();
                        }
                        Map.Entry<Character, Node> prefixWithSuffixes = prefixesWithSuffixes.next();
                        currentPrefix = prefixWithSuffixes.getKey();
                        if (null == currentPrefix) {
                            return "";
                        }
                        suffixesForCurrentPrefix = prefixWithSuffixes.getValue().iterator();
                    }
                    return currentPrefix + suffixesForCurrentPrefix.next();
                }

                private boolean outOfPrefixes() {
                    return !prefixesWithSuffixes.hasNext();
                }

                private boolean outOfSuffixesForCurrentPrefix() {
                    return !suffixesForCurrentPrefix.hasNext();
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            }
        }
    }
}

答案 3 :(得分:0)

public static List<String> crazySort(List<String> list) {
  LinkedHashMap<Character, List<String>> map = 
    new LinkedHashMap<Character, List<String>>();
  for (String s : list) {
    List<String> group = map.get(s.charAt(0));
    if (group == null)
      map.put(s.charAt(0), new ArrayList<String>());
    group.add(s);
  }
  List<String> sorted = new ArrayList<String>(list.size());
  for (List<String> group : map.values()) {
    sorted.addAll(group);
  }
  return sorted;
}