我有一个已根据数值排列的字符串列表。 现在我想按照以下方式对这些字符串进行分组。
假设我有一个如下所示的文本文件:
DBC
EB
CD
EDD
ACB
EBC
DAC
教育局
CDA
我希望以这样的方式订购它:
DBC
DAC
EB
EBC
EDD
教育局
CD
CDA
ACB
因此,您可以看到它必须按字符串的字母分组并将它们堆叠在一起。
什么是完成这项任务最有效的方法?
更新。 如您所见,所需的顺序不是按字母顺序排列的,包括反向顺序。正如我所提到的,目标是分组字符串并通过首次出现来对它们进行排序。对于这个例子,我使用字母来简化我想要解决的(很多)更复杂的问题。这里要集中注意力的是每个字符串的字母出现的顺序。按特定顺序分组,而不是订购。
答案 0 :(得分:2)
您需要的是前缀树(trie)。这是一棵树,其中每个级别对应于字符串中的位置(root = 0,级别1 =第一个字母等),并且每个节点对应于一个字母。
该节点还包含一个布尔值(比如isWord
),指定是否有一个单词在那里结束,在你的情况下你需要另一个int说index
,以指定你的初始单词的索引排序(如果isWord == true
)。
您也可以使用最初包含所有单词的Set。
现在只需开始遍历原始列表,对于未采取的每个单词,请执行以下操作:
希望有所帮助。
答案 1 :(得分:1)
好的,这看起来很复杂。如果我理解这一点,你需要一个两步解决方案:
您需要将多个字符串映射到公共前缀
public static String mapKey(String value){
// or whatever your mapping to a common key would be
return value.substring(0, 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
定义),因此它们将作为组返回。
实际上,在重新阅读您的要求时,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;
}