【问题标题】:Object Assign values from array rather than hard code对象从数组而不是硬代码中赋值
【发布时间】:2021-07-29 23:46:25
【问题描述】:

我正在尝试按多个属性对数据进行分组并对它们的值求和。

这是我按照this question尝试的方法

我对这个问题进行了跟进:

const arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];

const result = [...arr.reduce((r, o) => {
  const key = o.shape + '-' + o.color;
  
  const item = r.get(key) || Object.assign({}, o, {
    used: 0,
    instances: 0
  });
  
  item.used += o.used;
  item.instances += o.instances;

  return r.set(key, item);
}, new Map).values()];

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

我想通过数值使其更易于重用。例如,我想要

const item = r.get(key) || Object.assign({}, o, {
    used: 0,
    instances: 0
  });
  
  item.used += o.used;
  item.instances += o.instances;

部分特别是可重复使用的。

我得到了一个数组中的数值键:let gee = ['used', 'instances'];

我不确定如何将它与Object.assign 一起使用。我试着这样做:

const result = [...arr.reduce((r, o) => {
        const key = o.shape + '-' + o.color;
        // console.log(o);
        const item = gee.forEach(v => o[v] += o[v]);
        // const item = r.get(key) || Object.assign({}, o, {
        //  used: 0,
        //  instances: 0
        // });
        

        // item.used += o.used;
        // item.instances += o.instances;

        return r.set(key, item);
    }, new Map).values()];

但这不起作用。我如何在这段代码中使用数组:

const item = r.get(key) || Object.assign({}, o, {
    used: 0,
    instances: 0
  });
  
  item.used += o.used;
  item.instances += o.instances;

【问题讨论】:

    标签: javascript jquery arrays object ecmascript-6


    【解决方案1】:

    如果 Map 对象 has 是键,则循环遍历 totalKeys 并使用当前对象的数据递增累加器中的对象。如果是新的key,则将该对象的副本添加到Map中

    if (r.has(key)) {
      const item = r.get(key)
      totalKeys.forEach(k => item[k] += o[k])
    } else {
      r.set(key, { ...o })
    }
    

    这是一个sn-p:

    const arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];
    
    function groupSum(array, totalKeys) {
      const group = arr.reduce((r, o) => {
        const key = o.shape + '-' + o.color;
    
        if (r.has(key)) {
          const item = r.get(key)
          totalKeys.forEach(k => item[k] += o[k])
        } else {
          r.set(key, { ...o })
        }
        
        return r;
      }, new Map);
    
      return Array.from(group.values())
    }
    
    
    console.log(
      groupSum(arr, ['used', 'instances'])
    )
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    您可以通过提供一组键来分组,使其更加动态。使用由|分隔的对象的值创建key

    const key = groupKeys.map(k => o[k]).join("|");
    
    if (r.has(key)) {
      const item = r.get(key)
      totalKeys.forEach(k => item[k] += o[k])
    } else {
      r.set(key, { ...o })
    }
    

    这是一个sn-p:

    const arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];
    
    function groupSum(array, groupKeys, totalKeys) {
      const group = arr.reduce((r, o) => {
        const key = groupKeys.map(k => o[k]).join("|");
    
        if (r.has(key)) {
          const item = r.get(key)
          totalKeys.forEach(k => item[k] += o[k])
        } else {
          r.set(key, { ...o })
        }
        
        return r;
      }, new Map);
    
      return Array.from(group.values())
    }
    
    
    console.log(
      groupSum(arr, ['shape', 'color'], ['used', 'instances'])
    )

    【讨论】:

      【解决方案2】:

      您也可以通过不使用 array.reduce() 与 map() 的组合来极大地简化数据集...而是通过使用 array.forEach() 循环遍历原始数组的所有元素来构建新数组。 )。

      我添加了您对 gee 数组的使用作为您想要添加的数字字段的列表...包括确保它们存在于结果数组的每个对象上...无论它们是否存在于每个arr 中的先前对象。

      const arr = [{
        "shape": "square",
        "color": "red",
        "used": 1,
        "instances": 1
      }, {
        "shape": "square",
        "color": "red",
        "used": 2,
        "instances": 1
      }, {
        "shape": "circle",
        "color": "blue",
        "used": 0,
        "instances": 0
      }, {
        "shape": "square",
        "color": "blue",
        "used": 4,
        "instances": 4
      }, {
        "shape": "circle",
        "color": "red",
        "used": 1,
        "instances": 1
      }, {
        "shape": "circle",
        "color": "red",
        "used": 1,
        "instances": 0,
        "testProp": 1
      }, {
        "shape": "square",
        "color": "blue",
        "used": 4,
        "instances": 5
      }, {
        "shape": "square",
        "color": "red",
        "used": 2,
        "instances": 1
      }];
      
      let gee = ['used', 'instances', 'testProp'];
      let result = [];
      
      arr.forEach((o) => {
        // Setup TempSource since not all o may have all elements in gee
        let tempSource = {};
        gee.forEach((key) => {
          if (o.hasOwnProperty(key)) {
            tempSource[key] = o[key];
          } else {
            tempSource[key] = 0;
          }
        });
      
        // Look to see if the result array already has an object with same shape/color
        const matchingObject = result.find(element => {
          let returnValue = true;
          returnValue &= (element.shape == o.shape);
          returnValue &= (element.color == o.color);
          return returnValue;
        });
      
        if (matchingObject) {
          // Matching Object already exists... so increment values
          gee.forEach((key) => {
            matchingObject[key] += tempSource[key];
          });
        } else {
          // Matching Object missing, so merge newObject and insert
          let newObj = {};
          Object.assign(newObj, o, tempSource);
          result.push(newObj);
        }
      });
      
      console.log(result);
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

      【讨论】:

        【解决方案3】:

        也许这是一条路:

        const arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}],
        nums=["used","instances"]
        
        
        function summationOn(ar,cnts){ // cnts: add up counts on these properties
         const grp=Object.keys(ar[0]).filter(k=>cnts.indexOf(k)<0) // grp: group over these
         return Object.values(ar.reduce((a,c,t)=>{
          const k=grp.map(g=>c[g]).join("|");
          if (a[k]) cnts.forEach(p=>a[k][p]+=c[p])
          else a[k]={...c};
          return a
         },{}))
        }
        
        const res=summationOn(arr,nums);
        console.log(res);

        重写
        与@adiga 类似,我现在希望在数组cnts 中给出“可数”属性。使用这个数组,我将输入数组ar 的第一个对象的所有其他属性收集到数组grp 中。这些是我将分组的属性。

        【讨论】:

        • 他们有一个他们想要求和的属性数组。 let gee = ['used', 'instances']。他们不想像t.used+=c.used 那样硬编码
        • 啊 - 谢谢你告诉我。那么,如何识别求和的属性?!?
        • 您可以发送一组属性来求和。循环遍历数组并动态获取属性。您甚至可以使用一组属性按["shape", "color"] 分组。检查我的答案中的 sn-ps
        猜你喜欢
        • 2019-12-29
        • 2013-08-19
        • 2020-08-17
        • 1970-01-01
        • 1970-01-01
        • 2022-12-05
        • 1970-01-01
        相关资源
        最近更新 更多