2

我想从k. 条目是这样的:vHashMap

a = 3,4
b = 5,6

等等。我需要这些值的组合。

a=3, b=5
a=3, b=6
a=4, b=5
a=4, b=6

我不知道值有多少个键和多少个条目。有了entrySet我可以得到值,但不能得到组合。它看起来像递归,但如何?

这是我的代码:

HashMap<String, String[]> map = new HashMap<String, String[]>();

BufferedReader file = new BufferedReader(new FileReader("test.txt"));
String str;

while ((str = file.readLine()) != null) {
    
    // ... logic
    
    map.put(key, value);
}

System.out.println("number of keys: " + map.size());
for (Map.Entry<String, String[]> entry : map.entrySet()) {
    for (String value : entry.getValue()) {
        System.out.println(entry.getKey() + ": " + value);
    }
}
file.close();
4

3 回答 3

5

您可以尝试以下代码:

public void mapPermute(Map<String, String[]> map, String currentPermutation) {
    String key = map.keySet().iterator().next(); // get the topmost key

    // base case
    if (map.size() == 1) {          
        for (String value : map.get(key)) {
            System.out.println(currentPermutation + key + "=" + value);
        }
    } else {
        // recursive case
        Map<String, String[]> subMap = new HashMap<String, String[]>(map);

        for (String value : subMap.remove(key)) {
            mapPermute(subMap, currentPermutation + key + "=" + value + ", ");
        }
    }
}

不保证内存效率或速度。如果要保留映射中键的顺序,则必须传入 aTreeMap并更改代码以TreeMap在递归情况下使用 a。

正如基本情况所暗示的那样,我假设您的地图中至少有一个条目。

于 2011-03-16T10:25:04.100 回答
0

在我看来,你真的想要一个MultiMap. 特别是,ArrayListMultimap允许​​重复条目:

ArrayListMultimap<String, String> map = ArrayListMultimap.create();

for each line in file:
    parse key k
    for each value in line:
        parse value v
        map.put(k, v);

for (Map.Entry<String, String> entry : map.entries()) {
    String key = entry.getKey();
    String value = entry.getValue();
}

如果你想要地图的笛卡尔积,你可以直接使用递归计算,或者你可以迭代地图:创建一个迭代器列表并迭代里程表样式;当迭代器 N 到达终点时,推进迭代器 N+1 并重置迭代器 1..N。


只是四处逛逛,发现了这个问题

因此,我建议您将番石榴Sets.cartesianProduct用于笛卡尔积。这是我的代码,你可以适应你的输入逻辑:

String key1 = "a";
Set<Integer> values1 = Sets.newLinkedHashSet(Arrays.asList(1, 2, 3, 4));
String key2 = "b";
Set<Integer> values2 = Sets.newLinkedHashSet(Arrays.asList(5, 6, 7));
String key3 = "c";
Set<Integer> values3 = Sets.newLinkedHashSet(Arrays.asList(8, 9));

List<String> keys = Arrays.asList(key1, key2, key3);
Set<List<Integer>> product = Sets.cartesianProduct(values1, values2, values3);
for (List<Integer> values : product) {
    for (int i = 0; i < keys.size(); ++i) {
        String key = keys.get(i);
        int value = values.get(i);
        System.out.print(key + "=" + value + "; ");
    }
    System.out.println();
}
于 2011-03-16T09:09:31.203 回答
0

您可以使用map 和 reduce方法获得映射键值组合的笛卡尔积。

在线尝试!

Map<String, String[]> map = Map.of(
        "a", new String[]{"3", "4"},
        "b", new String[]{"5", "6"});
List<Map<String, String>> comb = map.entrySet().stream()
        // Stream<List<Map<String,String>>>
        .map(e -> Arrays.stream(e.getValue())
                .map(v -> Map.of(e.getKey(), v))
                .collect(Collectors.toList()))
        // summation of pairs of list into a single list
        .reduce((list1, list2) -> list1.stream()
                // combinations of inner maps
                .flatMap(map1 -> list2.stream()
                        // concatenate into a single map
                        .map(map2 -> {
                            Map<String, String> m = new HashMap<>();
                            m.putAll(map1);
                            m.putAll(map2);
                            return m;
                        }))
                // list of combinations
                .collect(Collectors.toList()))
        // otherwise, an empty list
        .orElse(Collections.emptyList());
// output, order may vary
comb.forEach(System.out::println);

输出,顺序可能会有所不同:

{a=3, b=5}
{a=3, b=6}
{a=4, b=5}
{a=4, b=6}

另请参阅:地图值的笛卡尔积

于 2021-08-13T13:16:33.733 回答