0

我有一个具有以下结构的对象数组:

var items = [
  {
    attributes: [
      {
        type: "Size",
        value: "Small"
      },
      {
        type: "Color",
        value: "Black"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Small"
      },
      {
        type: "Color",
        value: "White"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Medium"
      },
      {
        type: "Color",
        value: "Black"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Medium"
      },
      {
        type: "Color",
        value: "White"
      }
    ]
  }
];

我的目标是提取具有相同"type"的所有"value"属性。例如,“大小”类型具有以下值:小、中。之后,我想创建一个具有以下结构的新列表:

 var results = [
  {
    type: "Size",
    values: ["Small", "Medium"]
  },
  {
    type: "Color",
    values: ["White", "Black"]
  }
];

这是我当前的代码:

var results = items.map((item, index) => {
  return item.attributes.map(attribute => {
    let value = [];
    value.push(attribute.value);
    return {
      type: attribute.type,
      value: attribute.value
    };
  });
});
4

6 回答 6

2

您可以使用reduceSet

  • 首先循环遍历 items 数组
  • 对于每个属性,我们将typeas 映射到最终对象上并将值添加到相应的键,因为我们只想保留唯一值,因此我们使用Set
  • 现在我们的最终看起来像{type: { type, value }}但我们想要的格式是{ type, size}所以我们Object.values()用来获取然后我们将它映射到想要的{type, value}格式final

var items = [{attributes: [{type: "Size",value: "Small"},{type: "Color",value: "Black"}]},{attributes: [{type: "Size",value: "Small"},{type: "Color",value: "White"}]},{attributes: [{type: "Size",value: "Medium"},{type: "Color",value: "Black"}]},{attributes: [{type: "Size",value: "Medium"},{type: "Color",value: "White"}]}];


let final = items.reduce((op, {attributes}) => {
  attributes.forEach(({type, value}) => {
    op[type] = op[type] || {type, value: new Set()}
    op[type].value.add(value)
  })
  return op
},{})

let output = Object.values(final).map(({type, value}) => ({type, value:[...value]}))

console.log(output)

于 2019-07-14T06:14:56.063 回答
1

您可以首先将结构简化为 [type, value] 对。然后创建一个以类型为键的映射,将集合作为值(以保证值的唯一性),填充它,最后将该映射转换为所需的结构:

var items = [{attributes: [{type: "Size",value: "Small"},{type: "Color",value: "Black"}]},{attributes: [{type: "Size",value: "Small"},{type: "Color",value: "White"}]},{attributes: [{type: "Size",value: "Medium"},{type: "Color",value: "Black"}]},{attributes: [{type: "Size",value: "Medium"},{type: "Color",value: "White"}]}];

const pairs = items.flatMap(({attributes}) => attributes.map(({type, value}) => [type, value]));
const map = new Map(pairs.map(([type]) => [type, new Set]));
pairs.forEach(([type, value]) => map.get(type).add(value));
const result = Array.from(map, ([type, values]) => ({ type, values: [...values] }));

console.log(result);

于 2019-07-14T06:21:48.413 回答
1

var items = [
  {
    attributes: [
      {
        type: "Size",
        value: "Small"
      },
      {
        type: "Color",
        value: "Black"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Small"
      },
      {
        type: "Color",
        value: "White"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Medium"
      },
      {
        type: "Color",
        value: "Black"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Medium"
      },
      {
        type: "Color",
        value: "White"
      }
    ]
  }
];



var temp={};  // temporarly holder

items.forEach(function(item){  // iterate through each element
   item.attributes.forEach(function(attr){  // iterate through attributes of each element
   
    if (!temp[attr.type]) { temp[attr.type] = []; }  // if this is the first time we encounter
                                                       // this attribute, create a new placeholder
                                                       
    if(temp[attr.type].indexOf(attr.value)<0) {   // only add the attribute value if it was
                                                   // not added before
            temp[attr.type].push(attr.value);
    };
   });
});

var result = [];  // create the output result array

Object.keys(temp).forEach(function(key){  // iterate thought the keys of the temp object
  // add a new element with the properties congigured as desired
  result.push({type:key, values:temp[key]});
  
});

console.log(result);

于 2019-07-14T06:24:15.140 回答
1

var items = [
  {
    attributes: [
      {
        type: "Size",
        value: "Small"
      },
      {
        type: "Color",
        value: "Black"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Small"
      },
      {
        type: "Color",
        value: "White"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Medium"
      },
      {
        type: "Color",
        value: "Black"
      }
    ]
  },
  {
    attributes: [
      {
        type: "Size",
        value: "Medium"
      },
      {
        type: "Color",
        value: "White"
      }
    ]
  }
];

var results=[];
var type=[];
var values=[];

for(var i=0; i<items.length;i++){
  var x=items[i].attributes;
  for(var j=0; j<x.length;j++){
    var pos=type.indexOf(x[j].type);
    if(pos==-1){
      type.push(x[j].type);
      values.push([]);
      pos=type.length-1;
    }
    if(values[pos].indexOf(x[j].value)==-1) values[pos].push(x[j].value);
  }
}

for(var i=0; i<type.length;i++){
  results.push({type:type[i],values:values[i]})
}

console.log(results);

于 2019-07-14T06:34:49.750 回答
1

你不想使用 map,你想使用 reduce。

items.reduce(
    (acc, item) => {

        item.attributes.forEach(
            attribute => {
                let type = acc.find(type => type.type == attribute.type);

                if (!type) {
                    type = {type: attribute.type, values: []};
                    acc.push(type);
                }       

                if (!type.values.includes(attribute.value)) {
                    type.values.push(attribute.value);
                }
            }
        );

        return acc;
    }, []
)
于 2019-07-14T06:35:32.313 回答
0

这将产生稍微不同的输出。一个对象而不是对象数组。

let result = {};
items.forEach(item => item.attributes.forEach(att => { 
  if (result[att.type]) result[att.type].push(att.value);
  else result[att.type] = [att.value];
}));
于 2019-07-14T06:15:04.970 回答