根据属性值减少对象数组

时间:2021-11-23 22:31:10

I am trying to create a new array of object from an existing array of object based on the common attribute (category.blocktitle) value inside the object. My array of object looks like this.

我试图根据对象内部的公共属性(category.blocktitle)值从现有的对象数组创建一个新的对象数组。我的对象数组看起来像这样。

[
  {
    "category": {
      "name": "test1111",
      "val": "test111111111",
      "blocktitle": ".test.0"
    }
  },
  {
    "category": {
      "name": "test22",
      "val": "test2222",
      "blocktitle": ".test.0.test2"
    }
  },
  {
    "category": {
      "name": "test1111111",
      "val": "test11111111111",
      "blocktitle": ".test.0"
    }
  },
  {
    "category": {
      "name": "test2222",
      "val": "test222222",
      "blocktitle": ".test.0.test2"
    }
  }
]

My desired output is

我想要的输出是

[
  {
    "category": {
       "name_val" : [
              {
                     "name": "test1111",
                     "val": "test111111111"
              }, 
              { 
                     "name": "test1111111",
                     "val": "test11111111111",
              }
       ]
    },
    "blocktitle": ".test.0"
  },
  {
    "category": {
        "name_val" : [
                  {
                         "name": "test22",
                         "val": "test2222"
                  }, 
                  { 
                         "name": "test2222",
                         "val": "test222222",
                  }
        ]
    },
    "blocktitle": ".test.0.test2"
  }
]

I have tried reduce / map / filter but not sure what I am doing wrong.

我尝试过reduce / map / filter但不确定我做错了什么。

5 个解决方案

#1


3  

I would use ES6 Array.prototype.reduce and Array.prototype.filter methods:

我会使用ES6 Array.prototype.reduce和Array.prototype.filter方法:

let result = data.reduce((acc, d) => { 
  const found = acc.find(a => a.blocktitle === d.category.blocktitle);
  const value = { name: d.category.name, val: d.category.val };
  if(found) {
    found.category.name_val.push(value);
  }
  else {
    acc.push({blocktitle: d.category.blocktitle, category: { name_val: [value]} });
  }
  return acc;
}, []);

Where data is your initial data array.

数据是您的初始数据数组。

#2


3  

var test = [
  {
    "category": {
      "name": "test1111",
      "val": "test111111111",
      "blocktitle": ".test.0"
    }
  },
  {
    "category": {
      "name": "test22",
      "val": "test2222",
      "blocktitle": ".test.0.test2"
    }
  },
  {
    "category": {
      "name": "test1111111",
      "val": "test11111111111",
      "blocktitle": ".test.0"
    }
  },
  {
    "category": {
      "name": "test2222",
      "val": "test222222",
      "blocktitle": ".test.0.test2"
    }
  }
];

//create a map of blocktitle to elements with that blocktitle
var temp = test.reduce(function(collection, element){
  if (collection[element.category.blocktitle] === undefined) collection[element.category.blocktitle] = [];
  
  collection[element.category.blocktitle].push(element);
  return collection;
}, {});

//convert temp to expected result
var result = Object.keys(temp).map(function(blocktitle){
  return {
    blocktitle: blocktitle,
    category: {
      name_val: temp[blocktitle].map(function(element){
        return { name: element.category.name, val: element.category.val };
      })
    }
  };
});

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

#3


1  

You could use an object as reference to the same group.

您可以使用对象作为同一组的引用。

var data = [{ category: { name: "test1111", val: "test111111111", blocktitle: ".test.0" } }, { category: { name: "test22", val: "test2222", blocktitle: ".test.0.test2" } }, { category: { name: "test1111111", val: "test11111111111", blocktitle: ".test.0" } }, { category: { name: "test2222", val: "test222222", blocktitle: ".test.0.test2" } }],
    hash = Object.create(null),
    grouped = [];

data.forEach(function (o) {
    var key = o.category.blocktitle;
    if (!hash[key]) {
        hash[key] = [];
        grouped.push({ category: { name_val: hash[key], blocktitle: o.category.blocktitle } });
    }
    hash[key].push({ name: o.category.name, val: o.category.val });
});

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

#4


1  

You can use Array.prototype.reduce():

您可以使用Array.prototype.reduce():

const data = [{category: {name: 'test1111',val: 'test111111111',blocktitle: '.test.0'}},{category: { name: 'test22', val: 'test2222', blocktitle: '.test.0.test2' }},{category: {name: 'test1111111',val: 'test11111111111',blocktitle: '.test.0'}},{category: {name: 'test2222',val: 'test222222',blocktitle: '.test.0.test2'}}]
const result = data.reduce((a, c) => {
  let blocktitle = c.category.blocktitle;
  let objNameVal = { name: c.category.name, val: c.category.val };

  if (a.hash[blocktitle]) {
    let index = a.array.findIndex(e => e.blocktitle === blocktitle);
    a.array[index].category.name_val.push(objNameVal);
  } else {
    a.hash[blocktitle] = true;
    a.array.push({ category: { name_val: [objNameVal] }, blocktitle: blocktitle });
  }
  return a;
}, { array: [], hash: {} });

// Clean hash..
delete result.hash;

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

#5


0  

You can use a reduce to index the items by blocktitle, and then map that object to an array.

您可以使用reduce通过blocktitle索引项目,然后将该对象映射到数组。

function convert(input) {
  const byBlocktitle = input.reduce((byBlocktitleOut, inputObject) => {
    const blocktitle = inputObject.category.blocktitle;

    byBlocktitleOut[blocktitle] = byBlocktitleOut[blocktitle] || [];
    byBlocktitleOut[blocktitle].push(inputObject);

    return byBlocktitleOut;
  }, {});

  return Object.keys(byBlocktitle).map((blocktitle) => {
    const inputObjects = byBlocktitle[blocktitle];

    return {
      category: {
        name_val: inputObjects.map((inputObject) => {
          return {
            name: inputObject.category.name,
            val: inputObject.category.val,
          };
        }),
      },
      blocktitle: blocktitle,
    };
  });
}

Working example/test: http://jsbin.com/yifapacupi/edit?js,console,output

工作示例/测试:http://jsbin.com/yifapacupi/edit?js,console,output

#1


3  

I would use ES6 Array.prototype.reduce and Array.prototype.filter methods:

我会使用ES6 Array.prototype.reduce和Array.prototype.filter方法:

let result = data.reduce((acc, d) => { 
  const found = acc.find(a => a.blocktitle === d.category.blocktitle);
  const value = { name: d.category.name, val: d.category.val };
  if(found) {
    found.category.name_val.push(value);
  }
  else {
    acc.push({blocktitle: d.category.blocktitle, category: { name_val: [value]} });
  }
  return acc;
}, []);

Where data is your initial data array.

数据是您的初始数据数组。

#2


3  

var test = [
  {
    "category": {
      "name": "test1111",
      "val": "test111111111",
      "blocktitle": ".test.0"
    }
  },
  {
    "category": {
      "name": "test22",
      "val": "test2222",
      "blocktitle": ".test.0.test2"
    }
  },
  {
    "category": {
      "name": "test1111111",
      "val": "test11111111111",
      "blocktitle": ".test.0"
    }
  },
  {
    "category": {
      "name": "test2222",
      "val": "test222222",
      "blocktitle": ".test.0.test2"
    }
  }
];

//create a map of blocktitle to elements with that blocktitle
var temp = test.reduce(function(collection, element){
  if (collection[element.category.blocktitle] === undefined) collection[element.category.blocktitle] = [];
  
  collection[element.category.blocktitle].push(element);
  return collection;
}, {});

//convert temp to expected result
var result = Object.keys(temp).map(function(blocktitle){
  return {
    blocktitle: blocktitle,
    category: {
      name_val: temp[blocktitle].map(function(element){
        return { name: element.category.name, val: element.category.val };
      })
    }
  };
});

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

#3


1  

You could use an object as reference to the same group.

您可以使用对象作为同一组的引用。

var data = [{ category: { name: "test1111", val: "test111111111", blocktitle: ".test.0" } }, { category: { name: "test22", val: "test2222", blocktitle: ".test.0.test2" } }, { category: { name: "test1111111", val: "test11111111111", blocktitle: ".test.0" } }, { category: { name: "test2222", val: "test222222", blocktitle: ".test.0.test2" } }],
    hash = Object.create(null),
    grouped = [];

data.forEach(function (o) {
    var key = o.category.blocktitle;
    if (!hash[key]) {
        hash[key] = [];
        grouped.push({ category: { name_val: hash[key], blocktitle: o.category.blocktitle } });
    }
    hash[key].push({ name: o.category.name, val: o.category.val });
});

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

#4


1  

You can use Array.prototype.reduce():

您可以使用Array.prototype.reduce():

const data = [{category: {name: 'test1111',val: 'test111111111',blocktitle: '.test.0'}},{category: { name: 'test22', val: 'test2222', blocktitle: '.test.0.test2' }},{category: {name: 'test1111111',val: 'test11111111111',blocktitle: '.test.0'}},{category: {name: 'test2222',val: 'test222222',blocktitle: '.test.0.test2'}}]
const result = data.reduce((a, c) => {
  let blocktitle = c.category.blocktitle;
  let objNameVal = { name: c.category.name, val: c.category.val };

  if (a.hash[blocktitle]) {
    let index = a.array.findIndex(e => e.blocktitle === blocktitle);
    a.array[index].category.name_val.push(objNameVal);
  } else {
    a.hash[blocktitle] = true;
    a.array.push({ category: { name_val: [objNameVal] }, blocktitle: blocktitle });
  }
  return a;
}, { array: [], hash: {} });

// Clean hash..
delete result.hash;

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

#5


0  

You can use a reduce to index the items by blocktitle, and then map that object to an array.

您可以使用reduce通过blocktitle索引项目,然后将该对象映射到数组。

function convert(input) {
  const byBlocktitle = input.reduce((byBlocktitleOut, inputObject) => {
    const blocktitle = inputObject.category.blocktitle;

    byBlocktitleOut[blocktitle] = byBlocktitleOut[blocktitle] || [];
    byBlocktitleOut[blocktitle].push(inputObject);

    return byBlocktitleOut;
  }, {});

  return Object.keys(byBlocktitle).map((blocktitle) => {
    const inputObjects = byBlocktitle[blocktitle];

    return {
      category: {
        name_val: inputObjects.map((inputObject) => {
          return {
            name: inputObject.category.name,
            val: inputObject.category.val,
          };
        }),
      },
      blocktitle: blocktitle,
    };
  });
}

Working example/test: http://jsbin.com/yifapacupi/edit?js,console,output

工作示例/测试:http://jsbin.com/yifapacupi/edit?js,console,output