在JavaScript中将地图数据合并到数组中

时间:2018-08-21 09:47:07

标签: javascript arrays reduce

这是我当前的数组:

{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }

每行包含一个名为“实体”的属性,该属性有两行:一行对应于请求,另一行对应于响应。我需要合并请求和响应行,并将数据仅作为一行。 (属性“类型”在合并的行中无关紧要,但需要具有所有其他属性)。因此解决方案将类似于:

[{"entity":"A","type":"response","requestUrl":"val1","responseUrl":"val1"},
{"entity":"B","type":"response","requestUrl":"val1","responseUrl":"val1"},
{"entity":"C","type":"response","requestUrl":"val1","responseUrl":"val1"},
{"entity":"D","type":"response","requestUrl":"val1","responseUrl":"val1"}]

目前,这是我所拥有的: https://www.w3schools.com/code/tryit.asp?filename=FUHGQN2JON75

不确定这是否是最好的方法。欢迎提出有关如何改进此解决方案的建议。

谢谢。

7 个答案:

答案 0 :(得分:2)

一种选择是使用reduce将数组分组为一个对象。使用entity作为密钥。使用Object.assign转换对象。使用Object.values将对象转换为数组。

var arr = [{"entity":"A","type":"request","requestUrl":"val1"},{"entity":"A","type":"response","responseUrl":"val1"},{"entity":"B","type":"request","requestUrl":"val1"},{"entity":"B","type":"response","responseUrl":"val1"},{"entity":"C","type":"request","requestUrl":"val1"},{"entity":"C","type":"response","responseUrl":"val1"},{"entity":"D","type":"request","requestUrl":"val1"},{"entity":"D","type":"response","responseUrl":"val1"},{"entity":"DADA","type":"","responseUrl":"val1"}];

var result = Object.values(arr.reduce((c, v) => {
  c[v.entity] = Object.assign(c[v.entity] || {}, v);
  return c;
}, {}));

console.log(result);

答案 1 :(得分:0)

您可以使用Array.reduce()

var arr = [{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }];
var res = arr.reduce((acc, item)=>{
  var existObj = acc.find(obj => obj.entity === item.entity);
  if(!existObj){
    acc.push(item);
  } else {
     existObj['responseUrl'] = item.responseUrl;
  }
  return acc;
}, []);
console.log(res);

答案 2 :(得分:0)

您可以使用此答案

var arr = [{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }];

var res = Array.from(
  new Set(arr.filter(x => x.type).map(x=>x.entity))
)
.map(el => arr.find(obj => obj.entity === el))

console.log(res);// 
/* 
[{"entity":"A","type":"request","requestUrl":"val1"},
{"entity":"B","type":"request","requestUrl":"val1"},
{"entity":"C","type":"request","requestUrl":"val1"},
{"entity":"D","type":"request","requestUrl":"val1"}]
*/

答案 3 :(得分:0)

为此,您可以使用Map来跟踪所有实体对象。

稍后您可以将Map转换回数组。

const input = [
  { entity: 'A', type: 'request', requestUrl: 'val1' },
  { entity: 'A', type: 'response', responseUrl: 'val1' },
  { entity: 'B', type: 'request', requestUrl: 'val1' },
  { entity: 'B', type: 'response', responseUrl: 'val1' },
  { entity: 'C', type: 'request', requestUrl: 'val1' },
  { entity: 'C', type: 'response', responseUrl: 'val1' },
  { entity: 'D', type: 'request', requestUrl: 'val1' },
  { entity: 'D', type: 'response', responseUrl: 'val1' },
  { entity: 'DADA', type: '', responseUrl: 'val1' }
]

const entityMap = new Map();
input.forEach(element => {
  let currentEntity = entityMap.get(element.entity) || {};

  entityMap.set(element.entity, {
    ...currentEntity,
    ...element,
  })
});

return Array.from(entityMap.values());

答案 4 :(得分:0)

您可以使用MapforEach()

let data = [{ entity: 'A', type: 'request', requestUrl: 'val1' },{ entity: 'A', type: 'response', responseUrl: 'val1' },{ entity: 'B', type: 'request', requestUrl: 'val1' },{ entity: 'B', type: 'response', responseUrl: 'val1' },{ entity: 'C', type: 'request', requestUrl: 'val1' },{ entity: 'C', type: 'response', responseUrl: 'val1' },{ entity: 'D', type: 'request', requestUrl: 'val1' },{ entity: 'D', type: 'response', responseUrl: 'val1' }];

let result = ((a, m) => {
  a.forEach(o => {
    m.set(o.entity, Object.assign((m.get(o.entity) || {}), o));
  });
  return [...m.values()];
})(data, new Map());

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

答案 5 :(得分:0)

假设请求和响应是连续的,我们可以使用传播运算符进行合并

const data = [{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }]

const newData = data.reduce((acc, item, index) => {
  if (index % 2 || !item.type) return acc;
  acc.push({...item, ...data[index+1]})
  return acc;
}, [])

console.log(newData)

答案 6 :(得分:0)

使用reduce创建一个新数组。但是同时,如果数组中对象的顺序发生更改,则应检查输出。

让我们考虑这两个对象

{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' }

考虑第一个对象,在该对象中,我们将检查第二个对象中存在哪个键,但是现在在第一个对象中,然后将该键添加到第一个对象中。

let orgArray = [{
    entity: 'A',
    type: 'response',
    responseUrl: 'val1'
  },
  {
    entity: 'A',
    type: 'request',
    requestUrl: 'val1'
  },
  {
    entity: 'B',
    type: 'request',
    requestUrl: 'val1'
  },
  {
    entity: 'B',
    type: 'response',
    responseUrl: 'val1'
  },
  {
    entity: 'C',
    type: 'request',
    requestUrl: 'val1'
  },
  {
    entity: 'C',
    type: 'response',
    responseUrl: 'val1'
  },
  {
    entity: 'D',
    type: 'request',
    requestUrl: 'val1'
  },
  {
    entity: 'D',
    type: 'response',
    responseUrl: 'val1'
  },
  {
    entity: 'DADA',
    type: '',
    responseUrl: 'val1'
  }
]



let newArray = orgArray.reduce(function(acc, curr) {
  //get the index of the object where entity matches
  let getIndexOfEntity = acc.findIndex(function(item) {
    return item.entity === curr.entity
  })
  //if there is no such entity then it will give -1
  if (getIndexOfEntity === -1) {
    // in that case push the object
    acc.push(curr)
  } else {
    // if entity exist 
    //now check which key is missing from the
    // getting all the keys from both the object
    let getAllKeyFromAccObj = Object.keys(acc[getIndexOfEntity]);
    let getAllKeyFromCurrObj = Object.keys(curr)
    // looping through the key and adding the missing key 
    getAllKeyFromCurrObj.forEach(function(item) {
      if (getAllKeyFromAccObj.indexOf(item) === -1) {
        acc[getIndexOfEntity][item] = curr[item]
      }

    })
  }
  return acc;
}, [])

console.log(newArray)