Вот мой текущий массив выглядит так:

{ 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», который имеет 2 строки: одна соответствует запросу, а другая соответствует ответу. Мне нужно объединить строки запроса и ответа, и иметь данные только в одну строку. (Атрибут type не имеет значения в объединенной строке, но должен иметь все остальные атрибуты). Таким образом, решение будет что-то вроде:

[{"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

Не уверен, что это лучший способ сделать это. Приветствуются рекомендации по улучшению этого решения.

Спасибо.

3
Anirudh Chhabra 21 Авг 2018 в 12:47

7 ответов

Лучший ответ

Один из вариантов - использовать 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);
2
Eddie 21 Авг 2018 в 09:54

Вы можете использовать Map и forEach():

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; }
0
Mohammad Usman 21 Авг 2018 в 09:59

Предполагая, что запрос и ответ являются последовательными, мы можем просто использовать операторы спреда для объединения

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)
0
Prasanna 21 Авг 2018 в 10:01

Вы можете использовать этот ответ

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"}]
*/
0
аlex dykyі 21 Авг 2018 в 09:57

Вы можете использовать для этого карту. отслеживает все ваши объекты сущности.

Позже вы можете преобразовать 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());
0
Niekert 21 Авг 2018 в 09:59

Вы можете использовать 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);
0
Ankit Agarwal 21 Авг 2018 в 09:50

Используйте 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)
0
brk 21 Авг 2018 в 10:25
51945943