【问题标题】:JS, List of dictionary to dictionary of list, based on keyJS,字典列表到列表字典,基于键
【发布时间】:2026-01-15 02:35:01
【问题描述】:

我有一个字典列表,其中有一些属性,比如一个 url 和一些关于 url 的信息:

[{
    url:"https://example1.com/a"
    something:"ABC"
},{
    url:"https://example1.com/b"
    something:"DEF"
},{
    url:"https://example2.com/c"
    something:"GHI"
},{
    url:"https://example2.com/d"
    something:"JKL"
}]

现在我想把它拆分成一个列表字典,根据 url 分组。对于以上内容,我的目标数据结构是这样的:

{
    "example1.com" : [{
        url:"https://example1.com/a"
        something:"ABC"
    },{
        url:"https://example1.com/b"
        something:"DEF"
    }],
    "example2.com" : [{
        url:"https://example2.com/c"
        something:"GHI"
    },{
        url:"https://example2.com/d"
        something:"JKL"
    }]
}

在 python 中,这可以使用 itertools 包和一些列表理解技巧来实现,但我需要在 javascript/nodejs 中完成。

有人可以引导我在正确的方向上使用 javascript 执行此操作吗?

干杯。

【问题讨论】:

  • 你有没有尝试过?
  • 如何按值对对象属性进行分组已asked many times before。您肯定可以为您的问题找到现有的答案吗?此类广泛的问题可能会通过许多不同的方法得到解答,您确实应该先尝试一些方法,然后针对您的代码遇到的问题提出具体问题。

标签: javascript node.js dictionary


【解决方案1】:
data.reduce((groups, item) => {
    let host = new URL(item.url).hostname;
    (groups[host] || (groups[host] = [])).push(item);
    return groups;
}, {});

单线(虽然很神秘)

data.reduce((g, i, _1, _2, h = new URL(i.url).hostname) => ((g[h] || (g[h] =[])).push(i), g), {});

【讨论】:

    【解决方案2】:

    const dataFromQuestion = [{
        url:"https://example1.com/a",
        something:"ABC"
    },{
        url:"https://example1.com/b",
        something:"DEF"
    },{
        url:"https://example2.com/c",
        something:"GHI"
    },{
        url:"https://example2.com/d",
        something:"JKL"
    }];
    
    function listOfDictionaryToDictionaryOfList(input, keyMapper) {
      const result = {};
      for (const entry of input) {
        const key = keyMapper(entry);
        if (!Object.prototype.hasOwnProperty.call(result, key)) {
          result[key] = [];
        }
        result[key].push(entry);
      }
      return result;
    }
    
    function getHost(data) {
      const url = new URL(data.url);
      return url.host;
    }
    
    console.log(listOfDictionaryToDictionaryOfList(dataFromQuestion, getHost)); 

    【讨论】:

    • 是的。而已。可以肯定地使用它。干杯。
    • result[key] = (result[key] || []).push(entry);
    • 如果您将 result 初始化为 let result = Object.create(null) 您可以省去 hasOwnProperty 测试,因为 result 将只有自己的特性。而Object.prototype.hasOwnProperty.call(result, key) 似乎是不必要的冗长,为什么不result.hasOwnProperty(key)
    • @RobG 我不想假设 OP 程序的其余部分能够处理空原型对象。至于Object.prototype.hasOwnProperty.call,这是为了避免如果有key为“hasOwnProperty”的item会出现的错误。
    【解决方案3】:

    您可以在数组对象上使用reduce 方法。

    let data = [{
        url:"https://example1.com/a",
        something:"ABC"
    },{
        url:"https://example1.com/b",
        something:"DEF"
    },{
        url:"https://example2.com/c",
        something:"GHI"
    },{
        url:"https://example2.com/d",
        something:"JKL"
    }];
    
    let ret = data.reduce((acc, cur) => {
      let host = cur['url'].substring(8, 20); // hardcoded please use your own 
      if (acc[host])
        acc[host].push(cur);
      else
        acc[host] = [cur];
      return acc;
    }, {})
    
    console.log(ret);
    

    【讨论】: