首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >更新嵌套对象数组

更新嵌套对象数组
EN

Stack Overflow用户
提问于 2019-01-22 05:50:05
回答 3查看 1.4K关注 0票数 1

使用对象数组时,我需要更新任何typeSelect (Multiple Answer)的对象的计数。

每个typeSelect (Multiple Answer)的对象都包含一个data对象数组,其中包含一个逗号分隔的value,如“价格过高,独一无二,高质量”。这些值应该分离到它们自己的对象中,并包含在该特定count对象数组的新counttotal (所有count值的总和)中。

代码语言:javascript
运行
复制
const arr = [
  {
     data: [
       {count: 7, total: 7, value: "N/A"},
     ],
     name: "item 1",
     type: "Yes/No",
  }, {
     data: [
       {count: 5, total: 7, value: "N/A"},
       {count: 2, total: 7, value: "Yellow"},
     ],
     name: "item 2",
     type: "Select (Single Answer)",
  }, {
     data: [
       {count: 5, total: 7, value: "N/A"},
       {count: 1, total: 7, value: "Overpriced,Unique,High quality"},
       {count: 1, total: 7, value: "Reliable,High quality"},
     ],
     name: "item 3",
     type: "Select (Multiple Answer)",
  },
];

预期结果

代码语言:javascript
运行
复制
const result = [
  {
     data: [
       {count: 7, total: 7, value: "N/A"},
     ],
     name: "item 1",
     type: "Yes/No",
  }, {
     data: [
       {count: 5, total: 7, value: "N/A"},
       {count: 2, total: 7, value: "Yellow"},
     ],
     name: "item 2",
     type: "Select (Single Answer)",
  }, {
     data: [
       {count: 5, total: 10, value: "N/A"},
       {count: 2, total: 10, value: "High quality"},
       {count: 1, total: 10, value: "Overpriced"},
       {count: 1, total: 10, value: "Unique"},
       {count: 1, total: 10, value: "Reliable"},
     ],
     name: "item 3",
     type: "Select (Multiple Answer)",
  },
];

我已经开始使用reduce函数,但它产生的对象与预期结果相去甚远:

当前代码

代码语言:javascript
运行
复制
arr.reduce((a, c) => {
  a[c.data.value] = a[c.data.value] || { total: 0 };
  a[c.data.value].total += 1;
  return a;
}, {})

不想要的结果

代码语言:javascript
运行
复制
{ undefined: { total: 4 } }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-01-22 06:33:59

您可以收集这些组,并使用闭包获取total

它的特点是在total上使用闭包,并返回一个数组

代码语言:javascript
运行
复制
        data: (total => Array.from(


        ))(0)

通过以initialValue形式获取用于收集数据的Map

代码语言:javascript
运行
复制
             o.data.reduce(


                 new Map
            ),

以及用于用counttotalvalue映射新对象的函数。

代码语言:javascript
运行
复制
            ([value, count]) => ({ count, total, value })

reduce的回调中,countvalue被解构,值被拆分,以获得映射中收集的所有拆分值的所有计数。同时,total获得实际计数的增量。最后,返回地图m

代码语言:javascript
运行
复制
                 (m, { count, value }) => (value.split(',').forEach(
                     v => (m.set(v, (m.get(v) || 0) + count), total+= count)
                 ), m),

代码语言:javascript
运行
复制
var data = [{ data: [{ count: 7, total: 7, value: "N/A" }], name: "item 1", type: "Yes/No" }, { data: [{ count: 5, total: 7, value: "N/A" }, { count: 2, total: 7, value: "Yellow" }], name: "item 2", type: "Select (Single Answer)" }, { data: [{ count: 5, total: 7, value: "N/A" }, { count: 1, total: 7, value: "Overpriced,Unique,High quality" }, { count: 1, total: 7, value: "Reliable,High quality" }], name: "item 3", type: "Select (Multiple Answer)" }],
    result = data.map(o => Object.assign({}, o, {
        data: (total => Array.from(
             o.data.reduce(
                 (m, { count, value }) => (value.split(',').forEach(
                     v => (m.set(v, (m.get(v) || 0) + count), total+= count)
                 ), m),
                 new Map
            ),
            ([value, count]) => ({ count, total, value })
        ))(0)
    }));

console.log(result);
代码语言:javascript
运行
复制
.as-console-wrapper { max-height: 100% !important; top: 0; }

票数 3
EN

Stack Overflow用户

发布于 2019-01-22 06:40:27

这里有一种方法,可以通过一些注释来清楚地说明:

代码语言:javascript
运行
复制
let arr = [{data:[{count:7,total:7,value:"N/A"}],name:"item 1",type:"Yes/No"},{data:[{count:5,total:7,value:"N/A"},{count:2,total:7,value:"Yellow"}],name:"item 2",type:"Select (Single Answer)"},{data:[{count:5,total:7,value:"N/A"},{count:1,total:7,value:"Overpriced,Unique,High quality"},{count:1,total:7,value:"Reliable,High quality"}],name:"item 3",type:"Select (Multiple Answer)"}];

arr.forEach(x => {
  //get all splitted values
  const allValues = x.data.filter(y => y.value.split(',').length > 1).reduce((a, e) => a.concat(e.value.split(',')), []);

  //remove non-splitten values from data array
  x.data = x.data.filter(y => y.value.split(',').length <= 1);

  //create new values from old
  const newData = allValues.reduce((a, y) => {
    const data = a.find(z => z.value === y);
    if (data) {
      data.count++;
      return a;
    };
    return a.concat({ count: 1, value: y });
  }, x.data)
  
  //create new total
  const sumCounters = newData.reduce((a, e) => a + e.count, 0);
  newData.forEach(e => e.total = sumCounters);

  x.data = newData;
  return x;
})

console.log(arr);

票数 1
EN

Stack Overflow用户

发布于 2019-01-22 11:03:45

自从我开始写我的答案以来,已经提供了几个很好的答案,但我不想浪费时间,所以这里是我的解决方案。

代码语言:javascript
运行
复制
// OP's original array
const arr = [
  {
     data: [
       {count: 7, total: 7, value: "N/A"},
     ],
     name: "item 1",
     type: "Yes/No",
  }, {
     data: [
       {count: 5, total: 7, value: "N/A"},
       {count: 2, total: 7, value: "Yellow"},
     ],
     name: "item 2",
     type: "Select (Single Answer)",
  }, {
     data: [
       {count: 5, total: 7, value: "N/A"},
       {count: 1, total: 7, value: "Overpriced,Unique,High quality"},
       {count: 1, total: 7, value: "Reliable,High quality"},
     ],
     name: "item 3",
     type: "Select (Multiple Answer)",
  },
];

arr.forEach(function(select){
  // Only modify the multiple answer selects
  if(select.type == 'Select (Multiple Answer)'){
    var newTotal = 0; // calculate a new total as each item is added to the new array
    // use reduce to create a new data array for the multiple answer select
    var newDataArray = select.data.reduce(function(acc,d){
      valueArr = d['value'].split(','); // get a list of separate value strings
      valueArr.forEach(function(valStr){
        var unique = true;
        // if the new array is empty then go ahead and add the first item
        if(acc.length === 0){
          acc.push({'count':d.count,'total':d.total,'value':valStr});
          newTotal += d.count;
        } else {
          // check to see if there is already an object with the same value string
          // if there is then just update the count and set the unique flag so a new element doesn't get added later
          acc.forEach(function(obj){
            if(obj['value'] == valStr){
              obj['count'] += d.count;
              unique = false;
              newTotal += d.count;
            }
          })
          if(unique){
            acc.push({'count':d.count,'total':d.total,'value':valStr});
            newTotal += d.count;
          }      
        }          
      })
      return acc;
    }, []);
    // Update totals
    newDataArray.forEach(function(obj){
      obj.total = newTotal;
    })
    select.data = newDataArray;
  }
})
console.log(arr);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54298220

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档