Java 基于键将映射中的值中的值相互合并
我被这个奇怪的问题困扰了两个小时(我是哑巴) 我有一个带有Java 基于键将映射中的值中的值相互合并,java,arrays,merge,hashmap,maps,Java,Arrays,Merge,Hashmap,Maps,我被这个奇怪的问题困扰了两个小时(我是哑巴) 我有一个带有 A=1,2,3 B=4,5 C=6 我正在寻找的输出是 A=1&B=4&C=6 A=1&B=5&C=6 A=2&B=4&C=6 A=2&B=5&C=6 A=3&B=4&C=6 A=3&B=5&C=6 到目前为止我所做的:- 基于第一个键在映射上迭代,并将值存储在数组中 迭代第二个键,但我不确定如何将第一个结果中的值合并到此结果中 忘记第三个键和后续键 这听起来可能是一个非常愚蠢的问题,但我无法理解。我试图避免这种情况,但我无
- A=1,2,3
- B=4,5
- C=6
- A=1&B=4&C=6
- A=1&B=5&C=6
- A=2&B=4&C=6
- A=2&B=5&C=6
- A=3&B=4&C=6
- A=3&B=5&C=6
- 基于第一个键在映射上迭代,并将值存储在数组中
- 迭代第二个键,但我不确定如何将第一个结果中的值合并到此结果中
- 忘记第三个键和后续键
注意:-我也使用了multiset,但它接受重复的值作为值,因此必须使用一个集合。因此,最终得到了一个
map
以下代码可以处理地图的任何大小(空除外),以及每个集合的任何大小(空除外)。空映射/集将引发错误
当然,一旦定义了预期的输出,扩展代码以处理empty应该相当简单
Map<String, Set<String>> map = new LinkedHashMap<>();
map.put("A", new LinkedHashSet<>(Arrays.asList("1", "2", "3")));
map.put("B", new LinkedHashSet<>(Arrays.asList("4", "5")));
map.put("C", new LinkedHashSet<>(Arrays.asList("6")));
List<String> result = null;
for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
String key = (result == null ? "" : "&") + entry.getKey() + "=";
Set<String> values = entry.getValue();
if (values.isEmpty())
throw new IllegalArgumentException("Empty set not supported");
List<String> crossJoin = new ArrayList<>((result == null ? 1 : result.size()) * values.size());
if (result == null)
for (String value : values)
crossJoin.add(key + value);
else
for (String left : result)
for (String value : values)
crossJoin.add(left + key + value);
result = crossJoin;
}
if (result == null)
throw new IllegalArgumentException("Empty map not supported");
for (String value : result)
System.out.println(value);
以下代码可以处理地图的任何大小(空除外),以及每个集合的任何大小(空除外)。空映射/集将引发错误 当然,一旦定义了预期的输出,扩展代码以处理empty应该相当简单
Map<String, Set<String>> map = new LinkedHashMap<>();
map.put("A", new LinkedHashSet<>(Arrays.asList("1", "2", "3")));
map.put("B", new LinkedHashSet<>(Arrays.asList("4", "5")));
map.put("C", new LinkedHashSet<>(Arrays.asList("6")));
List<String> result = null;
for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
String key = (result == null ? "" : "&") + entry.getKey() + "=";
Set<String> values = entry.getValue();
if (values.isEmpty())
throw new IllegalArgumentException("Empty set not supported");
List<String> crossJoin = new ArrayList<>((result == null ? 1 : result.size()) * values.size());
if (result == null)
for (String value : values)
crossJoin.add(key + value);
else
for (String left : result)
for (String value : values)
crossJoin.add(left + key + value);
result = crossJoin;
}
if (result == null)
throw new IllegalArgumentException("Empty map not supported");
for (String value : result)
System.out.println(value);
如果您的代码停留一段时间,并且您可能希望更改格式或处理空案例,那么这里的答案更容易阅读,也更易于维护。它自然地处理带有空映射和没有允许值集的键的情况 我假设顺序对您不重要,但您可以用列表替换集合,以获得更可预测/一致的顺序
/**
* A nested pair class to handle the mappings like A:1.
*/
private static class Pair{
public Pair(String k,String v){
this.k = k;
this.v = v;
}
String k;
String v;
public String toString(){
return k+"="+v;
}
}
/**
* Given a set like
* {{A:"s1",B:"s4","C:s5"}
* {A:"s1",B:"s4","C:s6"}
* {A:"s2",B:"s4","C:s5"}
* {A:"s2",B:"s4","C:s6"}
* {A:"s3",B:"s4","C:s5"}
* {A:"s3",B:"s4","C:s6"}}
*
* Converts the contents to string like:
* A=s1&B=s4&C=s5
* A=s1&B=s4&C=s6
* A=s2&B=s4&C=s5
* A=s2&B=s4&C=s6
* A=s3&B=s4&C=s5
* A=s3&B=s4&C=s6
* @param pairCombinations
* @return
*/
public static String format(Set<Set<Pair>> pairCombinations){
String result = "";
for(Set<Pair> pairSet : pairCombinations){
result += formatPairSet(pairSet)+"\n";
}
return result;
}
private static String formatPairSet(Set<Pair> pairSet) {
String result = "";
boolean isFirst = true;
for(Pair pair : pairSet){
result+= (isFirst? "" : "&");
result += pair.k+"="+pair.v;
isFirst = false;
}
return result;
}
/**
* Given a map of the form:
* A:{"s1","s2","s3"}
* B:{"s4"}
* C:{"s5","s6"}
*
* Will return all possible combinations of pairs in
* the map as:
* {{A:"s1",B:"s4","C:s5"}
* {A:"s1",B:"s4","C:s6"}
* {A:"s2",B:"s4","C:s5"}
* {A:"s2",B:"s4","C:s6"}
* {A:"s3",B:"s4","C:s5"}
* {A:"s3",B:"s4","C:s6"}}
* @param map
* @return
*/
public static Set<Set<Pair>> getCombinations(Map<String,Set<String>> map){
Set<Set<Pair>> combinations = new HashSet<Set<Pair>>();
if(map.entrySet().isEmpty()){
return combinations;
}
combinations.add(new HashSet<Pair>());
Set<Pair> pairsForKey = null;
for(Entry<String,Set<String>> mapEntry : map.entrySet()){
//Ex: {C:"s5",C:"s6"}
pairsForKey = getPairs(mapEntry);
//Ex: {{A:s1,B:s4},{A:s2,B:s4},{A:s3,B:s4}}
combinations = join(combinations,pairsForKey);
}
return combinations;
}
private static Set<Pair> getPairs(Entry<String, Set<String>> kWithValidVs) {
Set<Pair> pairs = new HashSet<Pair>();
for(String v : kWithValidVs.getValue()){
pairs.add(new Pair(kWithValidVs.getKey(),v));
}
return pairs;
}
/**
* Given a set of combinations like:
* {{A:s1,B:s4},{A:s2,B:s4},{A:s3,B:s4}} and a set to join with it like {C:s5,C:s6},
* will join the set to the existing combinations like:
* {{A:s1,B:s4,C:s5},{A:s2,B:s4,C:s5},{A:s3,B:s4,C:s5},{A:s1,B:s4,C:s6},{A:s2,B:s4,A:s6},{A:s3,B:s4,C:s6}}
* @param combinations
* @param set
* @return
*/
private static Set<Set<Pair>> join(Set<Set<Pair>> combinations,
Set<Pair> set) {
Set<Set<Pair>> join = new HashSet<Set<Pair>>();
//comment this 'if' if you want keys with empty lists to eliminate all combos.
if(set.isEmpty()){
return combinations;
}
for(Set<Pair> combo : combinations){
for(Pair pair : set){
Set<Pair> newCombo = new HashSet<Pair>();
newCombo.addAll(combo);
newCombo.add(pair);
join.add(newCombo);
}
}
return join;
}
public static void main(String[] args){
Map<String,Set<String>> map = new HashMap<String,Set<String>>();
Set<String> aVals = new HashSet<String>();
aVals.add("1");
aVals.add("2");
aVals.add("3");
Set<String> bVals = new HashSet<String>();
bVals.add("4");
Set<String> cVals = new HashSet<String>();
cVals.add("5");
cVals.add("6");
map.put("A", aVals);
map.put("B", bVals);
map.put("C", cVals);
Set<Set<Pair>> combinations =getCombinations(map);
String printableResult = format(combinations);
System.out.print(printableResult);
}
如果您的代码停留一段时间,并且您可能希望更改格式或处理空案例,那么这里的答案更容易阅读,也更易于维护。它自然地处理带有空映射和没有允许值集的键的情况 我假设顺序对您不重要,但您可以用列表替换集合,以获得更可预测/一致的顺序
/**
* A nested pair class to handle the mappings like A:1.
*/
private static class Pair{
public Pair(String k,String v){
this.k = k;
this.v = v;
}
String k;
String v;
public String toString(){
return k+"="+v;
}
}
/**
* Given a set like
* {{A:"s1",B:"s4","C:s5"}
* {A:"s1",B:"s4","C:s6"}
* {A:"s2",B:"s4","C:s5"}
* {A:"s2",B:"s4","C:s6"}
* {A:"s3",B:"s4","C:s5"}
* {A:"s3",B:"s4","C:s6"}}
*
* Converts the contents to string like:
* A=s1&B=s4&C=s5
* A=s1&B=s4&C=s6
* A=s2&B=s4&C=s5
* A=s2&B=s4&C=s6
* A=s3&B=s4&C=s5
* A=s3&B=s4&C=s6
* @param pairCombinations
* @return
*/
public static String format(Set<Set<Pair>> pairCombinations){
String result = "";
for(Set<Pair> pairSet : pairCombinations){
result += formatPairSet(pairSet)+"\n";
}
return result;
}
private static String formatPairSet(Set<Pair> pairSet) {
String result = "";
boolean isFirst = true;
for(Pair pair : pairSet){
result+= (isFirst? "" : "&");
result += pair.k+"="+pair.v;
isFirst = false;
}
return result;
}
/**
* Given a map of the form:
* A:{"s1","s2","s3"}
* B:{"s4"}
* C:{"s5","s6"}
*
* Will return all possible combinations of pairs in
* the map as:
* {{A:"s1",B:"s4","C:s5"}
* {A:"s1",B:"s4","C:s6"}
* {A:"s2",B:"s4","C:s5"}
* {A:"s2",B:"s4","C:s6"}
* {A:"s3",B:"s4","C:s5"}
* {A:"s3",B:"s4","C:s6"}}
* @param map
* @return
*/
public static Set<Set<Pair>> getCombinations(Map<String,Set<String>> map){
Set<Set<Pair>> combinations = new HashSet<Set<Pair>>();
if(map.entrySet().isEmpty()){
return combinations;
}
combinations.add(new HashSet<Pair>());
Set<Pair> pairsForKey = null;
for(Entry<String,Set<String>> mapEntry : map.entrySet()){
//Ex: {C:"s5",C:"s6"}
pairsForKey = getPairs(mapEntry);
//Ex: {{A:s1,B:s4},{A:s2,B:s4},{A:s3,B:s4}}
combinations = join(combinations,pairsForKey);
}
return combinations;
}
private static Set<Pair> getPairs(Entry<String, Set<String>> kWithValidVs) {
Set<Pair> pairs = new HashSet<Pair>();
for(String v : kWithValidVs.getValue()){
pairs.add(new Pair(kWithValidVs.getKey(),v));
}
return pairs;
}
/**
* Given a set of combinations like:
* {{A:s1,B:s4},{A:s2,B:s4},{A:s3,B:s4}} and a set to join with it like {C:s5,C:s6},
* will join the set to the existing combinations like:
* {{A:s1,B:s4,C:s5},{A:s2,B:s4,C:s5},{A:s3,B:s4,C:s5},{A:s1,B:s4,C:s6},{A:s2,B:s4,A:s6},{A:s3,B:s4,C:s6}}
* @param combinations
* @param set
* @return
*/
private static Set<Set<Pair>> join(Set<Set<Pair>> combinations,
Set<Pair> set) {
Set<Set<Pair>> join = new HashSet<Set<Pair>>();
//comment this 'if' if you want keys with empty lists to eliminate all combos.
if(set.isEmpty()){
return combinations;
}
for(Set<Pair> combo : combinations){
for(Pair pair : set){
Set<Pair> newCombo = new HashSet<Pair>();
newCombo.addAll(combo);
newCombo.add(pair);
join.add(newCombo);
}
}
return join;
}
public static void main(String[] args){
Map<String,Set<String>> map = new HashMap<String,Set<String>>();
Set<String> aVals = new HashSet<String>();
aVals.add("1");
aVals.add("2");
aVals.add("3");
Set<String> bVals = new HashSet<String>();
bVals.add("4");
Set<String> cVals = new HashSet<String>();
cVals.add("5");
cVals.add("6");
map.put("A", aVals);
map.put("B", bVals);
map.put("C", cVals);
Set<Set<Pair>> combinations =getCombinations(map);
String printableResult = format(combinations);
System.out.print(printableResult);
}
“你总是有那三把准确的钥匙吗?”路易斯·沃瑟曼-不,钥匙会变。它们不是常数。允许使用外部库吗?@Louis Wasserman-no(输出应该是什么?在屏幕上打印这些组合?放入另一个数据结构(哪一个?)你总是有这三个精确的键吗?@Louis Wasserman-否。键会改变。它们不是常数。允许使用外部库吗?@Louis Wasserman-否:(输出应该是什么?在屏幕上打印这些组合?放入另一个数据结构(哪一个?)这是可行的。我有点被困在for内部。for无法理解如何继续。映射键和值不能为null或空白。此外,我还有另一个问题,即在多集值的情况下,是否有方法确保我们有唯一的值?因为输入是映射和设置的,所有值都是唯一的,除非您的意思是“a=1&B=1”无效。如果你的地图中有三个以上的列表,你可以一次加入两个列表,一直到最后。@Will,但我可能会丢失密钥的数据。我需要这两个数据。多年后,我再次遇到了同样的问题,并用javascript解决了这个问题!这很有效。我有点被困在中间,因为我无法找出如何处理并且映射键和值不能为null或空白。另外,我还有一个问题,即在多集值的情况下,是否有方法确保我们有唯一的值?因为输入是映射和设置的,所有值都是唯一的,除非您的意思是“a=1&B=1”无效。如果您的地图中有三个以上的列表,您可以一次加入两个列表,一直到最后。@Will,但我可能会丢失密钥的数据。我需要这两个数据。多年后我再次遇到同样的问题,并使用javascript解决了此问题!感谢您提供的解决方案。我一定会记住这一点。谢谢您提供的解决方案。我会的一定要记住这一点。