Преобразование массива объектов с использованием lodash или ramda

Эта проблема была вызвана конфликтом в банках модулей JBoss. Замена файла jboss-logging его последней версией решила проблему для меня. Файл находится в папке modules\system\layers\base\org\jboss\logging\main

Кроме того, вы должны заменить имя jar в файле module.xml новым именем jar. Файл находится в той же папке.

0
задан Ukasyah 14 July 2018 в 01:27
поделиться

4 ответа

Я бы использовал следующий подход, основанный на методах reduce и find (ES6):

const data = [
  { name: 'xx1', date: '2017-09-03', value: 49 },
  { name: 'xx2', date: '2017-10-23', value: 67 },
  { name: 'xx2', date: '2017-12-01', value: 70 }
];

const result = data.reduce((acc, item) => {
  const found = acc.find(a => a.name === item.name);
  if (found) {
     found.data[item.date] = item.value;
  } else {
    acc.push({
      name: item.name,
      data: {
        [item.date]: item.value
      }
    });
  }
  return acc;
}, []);

Если вы не хотите ES6, оба метода имеют версии lodash: уменьшить , найти .

2
ответ дан dhilt 17 August 2018 в 12:03
поделиться
  • 1
    Фантастика! Большое спасибо, шишо! Я никогда не знал о reduce раньше. Спасибо, что поделился :) – Ukasyah 14 July 2018 в 02:05

Для решения, использующего lodash, вы можете использовать его методы _.map, _.groupBy и _.merge для выполнения этого.

Я считаю, что проще использовать стиль _.chain но вы можете легко преобразовать его в обычный набор вложенных вызовов, если хотите.

const data = [
    { name: 'xx1', date: '2017-09-03', value: 49 },
    { name: 'xx2', date: '2017-10-23', value: 67 },
    { name: 'xx2', date: '2017-12-01', value: 70 },
]

const result = _.chain(data)
  .map(val => ({name: val.name, data: {[val.date]: val.value}})) // convert objects to desired format
  .groupBy("name")                                               // group objects by name
  .map(v => _.merge(...v))                                       // merge objects in each group
  .value();                                                      // done!
  
console.log(result);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>

1
ответ дан CRice 17 August 2018 в 12:03
поделиться

Вы можете скопировать объект с помощью Array#reduce() и вернуть его Object.values() :

const data = [
  { name: 'xx1', date: '2017-09-03', value: 49 },
  { name: 'xx2', date: '2017-10-23', value: 67 },
  { name: 'xx2', date: '2017-12-01', value: 70 }
]
const map = data.reduce((acc, { name, date, value }) => {
  if (!(name in acc)) {
    acc[name] = { name, data: {} }
  }

  acc[name].data[date] = value

  return acc
}, {})
const result = Object.values(map)

console.log(result)

Этот подход позволяет избежать использования Array#find(), которая является сложностью по времени O (n), и использует name in acc для проверки существования и acc[name] для доступа, которые являются одновременно сложностью O (1), что делает это подход O (n) в целом.

Напротив, другой ответ - общая сложность времени O (n2).

2
ответ дан Patrick Roberts 17 August 2018 в 12:03
поделиться

Ramda R.reduceBy или R.groupBy может вам помочь. В приведенном ниже примере R.reduceBy группирует объекты в массиве по свойству name, а затем объединяет сгруппированные элементы, создавая новый объект с помощью R.assoc . Остальная комбинация R.toPairs , R.map и R.zipObj вернет результат в нужную вам форму.

const fn = R.pipe(
  R.reduceBy((res, {date, value}) => R.assoc(date, value, res), {}, R.prop('name')),
  R.toPairs,
  R.map(R.zipObj(['name', 'data']))
)

const data = [
    { name: 'xx1', date: '2017-09-03', value: 49 },
    { name: 'xx2', date: '2017-10-23', value: 67 },
    { name: 'xx2', date: '2017-12-01', value: 70 }
]

console.log(fn(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

1
ответ дан Scott Christopher 17 August 2018 в 12:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: