用于聚合键包含数字的键值对的算法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用于聚合键包含数字的键值对的算法相关的知识,希望对你有一定的参考价值。
我会尽力给出一个完整的问题定义。为了说明这个问题,我将在后面的问题中给出一个例子。您可能希望先跳转到示例并在之后阅读我的问题定义。
问题
我有一张代表键值对的地图。密钥可以以-NUMBER
结尾,其中NUMBER
是整数。但是,也可能存在不以短划线和数字结尾的键。
领先的-NUMBER
之前的关键字也可能包含破折号。
可能有多个键以相同的字符串开头并以不同的数字结尾。
也可能有多个键以不同的字符串开头,也以数字结尾。
大体情况
- 所有钥匙都是独一无二
- 地图未订购
- 密钥的顺序是随机的
- 可以安全地假设键中的所有字符串都是大写的
- 如果有一个以短划线结尾的键和一个更大的数字
n
,则保证所有键以相同的字符串开头并以所有数字m
结尾,其中1 <m
<n
存在于地图中。 - 以数字结尾的原始密钥是否保留在最终集合中并不重要
专注于解决方案
解决方案不应该严格地关注优化运行时或空间复杂性,而是可读性和可维护性。地图中大约有200个条目,应用程序上预计不会有高流量。
例
输入:
{
"FIRST-KEY" = "FOO",
"SECOND-KEY-3"= "BAZ",
"THIRD-KEY-2" = "BAR",
"SECOND-KEY-1"= "FOO",
"SECOND-KEY-2"= "BAR",
"THIRD-KEY-1" = "FOO"
}
预期产出:
{
"FIRST-KEY" = "FOO",
"SECOND-KEY"= ["FOO", "BAR", "BAZ"],
"THIRD-KEY" = ["FOO", "BAR"]
}
或(如果原始密钥保留在结果中):
{
"FIRST-KEY" = "FOO",
"SECOND-KEY-3"= "BAZ",
"THIRD-KEY-2" = "BAR",
"SECOND-KEY-1"= "FOO",
"SECOND-KEY-2"= "BAR",
"THIRD-KEY-1" = "FOO",
"FIRST-KEY" = "FOO",
"SECOND-KEY" = ["FOO", "BAR", "BAZ"],
"THIRD-KEY" = ["FOO", "BAR"]
}
最后的笔记
我的解决方案必须在ColdFusion中实现。在我的问题开始时我必须将其称为map的输入在ColdFusion中称为struct。
您可以在ColdFusion(首选脚本语法)中表达您的答案,但您也可以选择您喜欢的任何其他语言(包括伪代码),只要您不使用我在ColdFusion中无法使用的其他语言的标准库。
如果保证所有数字1 ... n
都存在,一个简单的方法就是遍历所有的关键名称。对于每个键,使用正则表达式来提取“组”名称(即FIRST-KEY
,SECOND-KEY
等等)和可选的-NUMBER
后缀。
results = {};
for (key in structKeyArray(yourStruct)) {
keyGroup = reReplaceNoCase(key, "(.+)-d+$", "1", "ALL");
insertAt = reReplaceNoCase(key, "[^d+$]", "", "ALL");
isSequence = insertAt > 0;
// ....
如果数字> 0,则设置一个布尔标志,指示当前项是一系列相似键的一部分。然后检查您之前是否处理过当前的“组”。如果没有,请使用空数组初始化它。
if (isSequence && !results.keyExists( keyGroup )) {
results[ keyGroup ] = [];
}
最后,存储当前的“值”。如果当前项是序列的一部分,请将值插入现有数组中。 (由于-NUMBER
是顺序的,并且从1
开始,它可以用作数组索引,确保以正确的顺序插入值。)否则,只需将其存储为简单值。
if (isSequence) {
results[ keyGroup ][ insertAt ] = yourStruct[ key ];
}
else {
results[ keyGroup ] = yourStruct[ key ];
}
} // end loop
感谢Slack上的ColdFusion社区,我们提出了满足我要求的解决方案:
data = data.reduce(function(acc, k, v) {
var lastElement = listLast(k, '-');
if(isNumeric(lastElement)) {
var newKey = reReplace(k, '-d+$', '');
// init array if not initialized yet
if(!acc.keyExists(newKey)) acc[newKey] = [];
acc[newKey][lastElement] = v;
}
// may be put into an else block. This is only in here to attach the original keys in any case
acc[k] = v;
return acc;
}, {});
IMO它非常简洁,紧凑和优雅。此外,它主要是自我解释的,可以直观地理解。
这个想法是,整个问题可以归结为一个reduction。对于每个元素,我们查看最后一个“段”(由-
分隔),如果它是数字,我们可以为该键构建additoinal数组。
如果有人不同意或有更好的解决方案,我会非常乐意看到它。
最后感谢qazxsw poi的努力,解决方案的积分去了qazxsw poi
以上是关于用于聚合键包含数字的键值对的算法的主要内容,如果未能解决你的问题,请参考以下文章
java问题,我想在java中存储键值对,以便使用,但是键值对的键和值都有重复元素,使用hashmap会产生覆盖。