【问题标题】:Associate two arrays according to a number of key value根据多个键值关联两个数组
【发布时间】:2021-03-25 12:53:33
【问题描述】:

我想在两个对象数组之间建立关联,但我一直坚持这一点。 说明:

我有一系列不同的参考产品

const array1 = [
{name: peanuts, referenceKey: 0}, 
{name: almond, referenceKey: 1}, 
{name: nuts, referenceKey: 2}, 
{name: cream, referenceKey: 3}
] 

我有另一个开放参考产品表,除了每个开放产品的特定密钥外,还有一个到期日期和与 array1 中的参考密钥相同的参考密钥

const array2 = [
 {name: peanuts, expirationDate: "30d", referenceKey:0, otherKey: 42}, 
 {name: peanuts, expirationDate: "20d", referenceKey:0, otherKey: 43}, 
 {name: peanuts, expirationDate: "15h", referenceKey:0, otherKey: 44}, 
 {name: almond, expirationDate: "30d", referenceKey:1, otherKey: 45},
 {name: cream, expirationDate: "1d", referenceKey: 3, otherKey: 46},
 {name:cream, expirationDate: "12h", referenceKey: 3, otherKey: 47}
] 

我想做的是计算打开的array2 的相同产品的数量,并基于array1 将这个数字推入一个新的array,如下所示:

const array3 = [
 {name: peanuts, referenceKey: 0, opened: 3}, 
 {name: almond, referenceKey: 1, opened: 1}, 
 {name: nuts, referenceKey: 2, opened: 0}, 
 {name: cream, referenceKey: 3, opened: 2}
] 

我尝试使用 Reduce() 方法按名称重新组合 array2,如下所示:

    const groupByName = (products, name) => {
        return products.reduce((acc, obj) => {
            var key = obj[name];
            if (!acc[key]) {
                acc[key] = []
            }
            acc[key].push(obj);
            return acc
        }, [])
    };

    const groupByName = groupByReference(array2, "name")
    console.log(groupByName)
    

groupByName 的输出:

  [
    [peanuts:
    [
        {name: peanuts, expirationDate: "30d", referenceKey: 0, otherKey: 42}, 
        {name: peanuts, expirationDate: "20d", referenceKey:0, otherKey: 43}, 
        {name: peanuts, expirationDate: "15h", referenceKey:0, otherKey: 44}, 
    ],
    cream: [
        {name: cream, expirationDate: "1d", referenceKey: 3, otherKey: 46 },
        {name: cream, expirationDate: "12h", referenceKey: 3, otherKey: 47}
    ],
    almond: [
        {name: almond, expirationDate: "30d", referenceKey:1, otherKey: 45},
    ]
 ]

然后我尝试检索每个数组的长度,但我不明白。我尝试使用 Map() 方法,但它不起作用。

即使我像 groupByName['peanuts'] 这样指定索引,console.log() 也会返回正确的数组。但是使用groupByName['peanuts'].length 不起作用。

【问题讨论】:

  • 可能只是问题的拼写错误,但要指出的是,如果值不是变量,name: cream 是语法错误。如果它是文字,那么您忘记在所有这些地方加上引号。

标签: javascript arrays sorting multidimensional-array associative-array


【解决方案1】:

您可以获取一个对象,既可以用于生成结果集,也可以用于计算相同命名的对象。

const
    array1 = [{ name: "peanuts", referenceKey: 0 }, { name: "almond", referenceKey: 1 }, { name: "nuts", referenceKey: 2 }, { name: "cream", referenceKey: 3 }],
    array2 = [{ name: "peanuts", expirationDate: "30d", referenceKey: 0, otherKey: 42 }, { name: "peanuts", expirationDate: "20d", referenceKey: 0, otherKey: 43 }, { name: "peanuts", expirationDate: "15h", referenceKey: 0, otherKey: 44 }, { name: "almond", expirationDate: "30d", referenceKey: 1,  otherKey: 45 }, { name: "cream", expirationDate: "1d", referenceKey: 3, otherKey: 46 }, { name: "cream", expirationDate: "12h", referenceKey: 3, otherKey: 47 }],
    temp = {},
    result = array1.map(o => temp[o.name] = { ...o, open: 0 });

array2.forEach(o => temp[o.name].open++);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:
    let array3 = array1
    for( let element of array3 ) {
      element['opened'] = array2.filter(el => el.referenceKey == element.referenceKey).length  
    }
    

    【讨论】:

      【解决方案3】:

      如果我正确理解了您的问题,我认为这就是您的原始请求。

      您可以按namereferenceKey 进行分组,因为它们存在于两个数组中,但不是expirationDate

      const array1 = [
        { name: "peanuts", referenceKey: 0 },
        { name: "almond", referenceKey: 1 },
        { name: "nuts", referenceKey: 2 },
        { name: "cream", referenceKey: 3 },
      ];
      
      const array2 = [
        { name: "peanuts", expirationDate: "30d", referenceKey: 0, otherKey: 42 },
        { name: "peanuts", expirationDate: "20d", referenceKey: 0, otherKey: 43 },
        { name: "peanuts", expirationDate: "15h", referenceKey: 0, otherKey: 44 },
        { name: "almond", expirationDate: "30d", referenceKey: 1, otherKey: 45 },
        { name: "cream", expirationDate: "1d", referenceKey: 3, otherKey: 46 },
        { name: "cream", expirationDate: "12h", referenceKey: 3, otherKey: 47 },
      ];
      
      const groupByKey = (products, instances, key) => {
        return products.reduce((acc, obj) => {
          // Count matching instances matching
          const opened = instances.filter((instance) => instance[key] === obj[key])
            .length;
      
          // Append to accumulator array, uses spread, for immutability.
          acc = [
            ...acc,
            {
              name: obj.name,
              referenceKey: obj.referenceKey,
              opened,
            },
          ];
      
          return acc;
        }, []);
      };
      
      const array3 = groupByKey(array1, array2, "name");
      console.log(array3);

      【讨论】:

        【解决方案4】:

        我可能会从一个辅助函数开始,该函数会在将提供的函数应用于它们时计算所有产生给定值的对象。类似的东西

        countBy (x => x.a) ([{a: 'p', b: 'm'}, {a: 'q', b: 's'}, 
                             {a: 'p', b: 't'}, {a: 'r', b: 'v'}])
        //=> {p: 2, q: 1, r: 1}
        

        因为其中两个对象的a 值为'p',一个具有'q',一个具有'r'

        我们可以使用它来通过referenceKey 计算我们的对象(name 如果它应该是一个字符串而不是对问题中某个对象的引用),然后简单地映射到我们的定义对象,从该结果中添加适当的opened 属性(如果我们没有找到,则添加0。)

        它可能看起来像这样:

        const countBy = (fn) => (xs) => 
          xs.reduce((a, x, _, __, key = fn(x)) => ({...a, [key] : (a[key] || 0) + 1}), {})
        
        const opened = (defs, instances, counts = countBy (x => x.referenceKey) (instances)) =>
          defs.map (def => ({...def, opened: counts[def.referenceKey] || 0}))
        
        
        const array1 = [{name: 'peanuts', referenceKey: 0}, {name: 'almond', referenceKey: 1}, {name: 'nuts', referenceKey: 2}, {name: 'cream', referenceKey: 3}] 
        const array2 = [{name: 'peanuts', expirationDate: "30d", referenceKey:0, otherKey: 42}, {name: 'peanuts', expirationDate: "20d", referenceKey:0, otherKey: 43}, {name: 'peanuts', expirationDate: "15h", referenceKey:0, otherKey: 44}, {name: 'almond', expirationDate: "30d", referenceKey:1, otherKey: 45}, {name: 'cream', expirationDate: "1d", referenceKey: 3, otherKey: 46}, {name: 'cream', expirationDate: "12h", referenceKey: 3, otherKey: 47}] 
        
        console .log (opened (array1, array2))
        .as-console-wrapper {max-height: 100% !important; top: 0}

        但你也走在了正确的轨道上。你可以使用你的groupByName(在你解决了groupByName的两个定义和groupByReference之一之间的命名问题之后)像这样:

        const groupedByName = groupByName (array2, "name")
        
        array1 .map (({name, ...rest}) => ({
          name, 
          ...rest, 
          opened: (groupedByName[name] || []).length
        }))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多