Преобразование массива объектов в новую структуру массива

Извиняюсь, но я изучаю манипулирование массивами, пробовал кое-что, как и раньше, но просто не могу понять это. Я создаю приложение для реагирования и получил свои данные обратно из пользовательского интерфейса, но мне нужно переформатировать для API. Мой груз выглядит так...

0: {from: "U20", Id: "1922", to: "U21"}
1: {from: "U20", Id: "9338", to: "U21"}
2: {from: "U20", Id: "1927", to: "U21"}
3: {from: "U20", Id: "1730", to: "U21"}

Мне нужно создать группу для всех ids и опубликовать поля from и to.

{
    "from": "U20",
    "Ids": ["1922","9338","1927","1730"],
    "to:": "U21"
}

У меня есть lodash в качестве вспомогательной библиотеки.

могли бы вы иметь более одного значения from и to?

Nina Scholz 12.02.2019 14:52

Нет, извините, забыл сказать, эти значения пока будут одинаковыми.

Tom Rudge 12.02.2019 14:54
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
89
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Ответ принят как подходящий

Для группировки по 2-м ключам можно сделать что-то подобное с помощью reduce. Создайте объект-аккумулятор с новым ключом, представляющим собой комбинацию from и to.

const input = [
    { from: "U20", Id: "1922", to: "U21" },
    { from: "U20", Id: "9338", to: "U21" },
    { from: "U20", Id: "1927", to: "U21" },
    { from: "U20", Id: "1730", to: "U21" }
];

const merged = input.reduce((acc, { from, to, Id }) => {
    const key = `${from}-${to}`;
    acc[key] = acc[key] || { from, to, Ids:[] };
    acc[key]["Ids"].push(Id);
    return acc;
}, {})

const output = Object.values(merged);
console.info(output);

В вашем случае, если вы хотите просто первый объект, то output[0]

Если есть вероятность того, что в полях from и to будут разные значения, тогда ваш API должен измениться, чтобы принимать массив значений вместо одной строки. Однако, работая в предположении, что значения from и to всегда будут одинаковыми для каждого элемента в массиве...

const payload = [
  {from: "U20", Id: "9338", to: "U21"},
  {from: "U20", Id: "1927", to: "U21"},
  {from: "U20", Id: "1730", to: "U21"},
];

const newValue = {
  from: payload[0].from,
  to: payload[0].to,
  Ids: payload.map(item => item.Id)
};

Используйте уменьшение массива и в аккумуляторе передайте пустой объект. С помощью hasOwnProperty проверить, есть ли у объекта свойство from и если его значение совпадает, то в массив id протолкнуть значение

let data = [{
    from: "U20",
    Id: "1922",
    to: "U21"
  },
  {
    from: "U20",
    Id: "9338",
    to: "U21"
  },
  {
    from: "U20",
    Id: "1927",
    to: "U21"
  },
  {
    from: "U20",
    Id: "1730",
    to: "U21"
  }
]


let newData = data.reduce(function(acc, curr) {
  if (acc.hasOwnProperty('from') && acc.from === curr.from) {
    acc.id.push(curr.Id)
  } else {
    acc = {
      from: curr.from,
      id: [curr.Id],
      to: curr.to
    }

  }
  return acc;
}, {});

console.info(newData)

const a = [
  {from: "U20", Id: "1922", to: "U21"},
  {from: "U20", Id: "9338", to: "U21"},
  {from: "U20", Id: "1927", to: "U21"},
  {from: "U20", Id: "1730", to: "U21"},
  {from: "U21", Id: "1745", to: "U22"},
  {from: "U21", Id: "1755", to: "U22"},
]

const f = array => {
  const result = []
  // key-value storage
  const variations = {}
  array.forEach(item => {
    // set storage key
    const key = `${item.from}-${item.to}`;
    // check if key exists
    // if exists use it, if not - create empty array
    variations[key] = variations[key] || []
    // push item ids to storage
    variations[key].push(item.Id)
  })
  Object.keys(variations).map(variation => {
    // deconstruct storage key back to "from" and "to" values
    const [from, to] = variation.split('-');
    const obj = {};
    // write "from" and "to" values
    obj.from = from;
    obj.to = to;
    // add stored values
    obj.ids = variations[variation]
    // save
    result.push(obj)
  })
  console.info(result)
}

f(a)

С помощью следующего вы можете вести учет каждого списка Ids для каждой пары ключей from -> to.

const entries = [
	{ from: 'U20', to: 'U21', Id: '1922' },
	{ from: 'U20', to: 'U21', Id: '9338' },
	{ from: 'U20', to: 'U21', Id: '1927' },
	{ from: 'U20', to: 'U21', Id: '1730' },
]

const output = entries.reduce((map, {from, to, Id}) =>
{
	if (!map[from])
	{
		map[from] = {}
	}
	
	if (!map[from][to])
	{
		map[from][to] = {from, to, Ids: []}
	}
	
	map[from][to].Ids.push(Id)
	
	return map
}, {})

console.info(output)

Попробуй это

var idArray = [];
var newObj = {};
 var objArray = [{
    "from": "U20",
    "Id": "1922",
    "to": "U21"
},
{
    "from": "U20",
    "Id": "9338",
    "to": "U21"
},
{
    "from": "U20",
    "Id": "1927",
    "to": "U21"
},
{
    "from": "U20",
    "Id": "1730",
    "to": "U21"
}
]

      for(var i=0; i<objArray.length; i++) {
    for(var key in objArray[i]) {
      if (key == 'Id') idArray.push(objArray[i][key])
    }
  }
  newObj.from = objArray[0].from;
  newObj.to = objArray[0].to;
  newObj.Id = idArray;
  console.info(JSON.stringify(newObj));

Немного другой подход, использующий Map и объединенный ключ для группировки с двумя значениями.

var data = [{ from: "U20", Id: "1922", to: "U21" }, { from: "U20", Id: "9338", to: "U21" }, { from: "U20", Id: "1927", to: "U21" }, { from: "U20", Id: "1730", to: "U21" }, { from: "U20", Id: "1730", to: "U22" }, { from: "U21", Id: "1730", to: "U22" }],
    result = Array.from(data
        .reduce(
             (m, { from, to, Id }) =>
                 (k => m.set(k, { from, to, Ids: [...(m.has(k) ? m.get(k).Ids : []), Id] }))
                 ([from, to].join('|')),
             new Map
        )
        .values()
    );

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

И еще одно решение:

const compare = (o1, o2) => o1.from === o2.from && o1.to === o2.to
return entries
    .reduce((arr,entry) => !arr.find(a=>compare(a,entry)) ? arr.concat(entry) : arr, [])
    .map( ({from,to})=> ({
        from,
        to,
        ids: entries.filter(i=>compare(i,{from,to})).map(({id})=>id)
        }))

Это решение использует Лодаш/fp для группировки всех объектов в массиве с помощью комбинации реквизитов from и to. Затем он отображает все группы обратно в массив, объединяя все объекты в каждой группе. Если объединенный реквизит — Id, он объединяет значения в массив.

const { flow, groupBy, props, join, map, mergeAllWith, cond, nthArg, eq, concat } = _;

const fn = flow(
  groupBy(flow(                // group by joining from and to as the key
    props(['from', 'to']),
    join('-')
  )),
  map(mergeAllWith(cond([[     // merge all objects in each group
    flow(nthArg(2), eq('Id')), // if the prop name is Id, concat the values
    concat
  ]])))
);

const input = [
    { from: "U20", Id: "1922", to: "U21" },
    { from: "U20", Id: "9338", to: "U21" },
    { from: "U20", Id: "1927", to: "U21" },
    { from: "U20", Id: "1730", to: "U21" }
];

const result = fn(input);

console.info(result);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

Это просто. Ты можешь это сделать

const arr = [
     {from: "U20", Id: "1922", to: "U21"},
     {from: "U20", Id: "9338", to: "U21"},
     {from: "U20", Id: "1927", to: "U21"},
     {from: "U20", Id: "1730", to: "U21"}]

const newObject = {
    from: arr[0].from,
    Ids: arr.map(record => (record.Id)),
    to: arr[0].to
    }

Другие вопросы по теме