聚合键值对(其中键包含数字)的算法

时间:2019-04-24 16:18:12

标签: algorithm coldfusion set-theory

我将尽力给出完整的问题定义。为了说明这个问题,我将在稍后的问题中给出一个示例。 您可能想先跳到示例,然后再阅读我的问题定义。

问题

我有一个表示键值对的映射。键可以以-NUMBER结尾,其中NUMBER是整数。但是,可能还会有一些不以破折号和数字结尾的键。

前导-NUMBER之前的键也可能包含破折号。

可能有多个键,它们以相同的字符串开头,以不同的数字结尾。

可能还有多个键,它们以不同的字符串开头,也以数字结尾。

一般条件

  1. 所有键都是唯一的
  2. 地图未排序
  3. 键的顺序是随机的
  4. 可以安全地假设键中的所有字符串均为大写字母
  5. 如果有一个以破折号和数字n 更大结尾的键,则可以确保所有键都以相同的字符串开头并以所有数字结尾{{地图中存在1}}和1 <{m <m
  6. 以数字结尾的原始键是否保留在最终集中都没关系

关注解决方案

该解决方案不应严格关注于优化运行时或空间复杂性,而应着眼于可读性和可维护性。 地图中最多约有200个条目,并且应用程序预计不会带来高流量。

示例

输入:

n

预期输出:

{
    "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中实现。 在问题开始时我必须将其称为地图的输入在ColdFusion领域称为struct

您可以使用ColdFusion(首选脚本语法)来制定答案,但只要您不使用我无法在ColdFusion中使用的另一种语言的标准库,也可以选择您喜欢的任何其他语言(包括伪代码)

2 个答案:

答案 0 :(得分:4)

如果保证所有数字1 ... n都存在,则一种简单的方法是仅遍历所有键名。对于每个键,请使用正则表达式提取“组”名称(即FIRST-KEYSECOND-KEY等)和 optional -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

答案 1 :(得分:1)

由于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。 对于每个元素,我们查看最后一个“段”(由-分隔),如果它是数字,则可以为该键构建附加数组。

如果有人不同意或有更好的解决方案,我将很高兴看到它。

最后感谢effords Ageax,为此解决方案赢得了rodel30