Как сопоставить несколько свойств с массивами в Angular 6?

#angular #rxjs #rxjs-pipeable-operators

#angular #rxjs #rxjs-конвейерные операторы

Вопрос:

У меня есть массив объектов, таких как:

 const data: any[] = [
     { x: 1, y: 1 },
     { x: 2, y: 2 },
     { x: 3, y: 4 },
     { x: 4, y: 6 }
];

// get x as array
from(d).pipe(map(m => m.x), toArray()).subscribe(x => ...);
  

И хотел бы сопоставить его с чем-то вроде приведенного ниже, чтобы использовать его в Plotly

 {
  x: [1,2,3,4],
  y: [1,2,4,6]
}
  

Конечно, я мог бы дублировать канал выше, чтобы получить значения y, но это были бы разные подписки. Есть ли другой способ решить эту проблему?

Ответ №1:

Не связано с RxJS, это просто обычный JS.

Используйте reduce следующим образом :

 const data = [
     { x: 1, y: 1 },
     { x: 2, y: 2 },
     { x: 3, y: 4 },
     { x: 4, y: 6 }
];

const plotly = data.reduce((p, n) => ({ 
  x: [...p.x, n.x], 
  y: [...p.y, n.y]
}), { 
  x: [], 
  y: []
});

console.log(plotly);  

Ответ №2:

Давайте здесь применим немного магии ES6. Мы будем использовать синтаксис spread и Object.assign . В некотором смысле, мы как бы транспонируем этот массив объектов.

 const data = [
     { x: 1, y: 1 },
     { x: 2, y: 2 },
     { x: 3, y: 4 },
     { x: 4, y: 6 }
];

const result = Object.assign(...Object.keys(data[0]).map(key =>
  ({ [key]: data.map( o => o[key] ) })
));

console.log(result)  

Комментарии:

1. Вау, я должен проверить, что происходит внутри этой магии. Но мне пришлось добавить цель Object.assign({},... для ее компиляции. Спасибо!

2. @alex555 Да, я признаю, что это может быть немного сложно для чтения! решение тричетриче кажется наиболее читаемым среди всех ответов здесь!

Ответ №3:

Вместо этого используйте rxjs reduce

 from(this.data).pipe(
  reduce((acc, m) => {
    acc.x.push(m.x);
    acc.y.push(m.y);
    return acc
  }, {x: [], y: []})).subscribe(x => console.log(x));
  

https://stackblitz.com/edit/angular-gldpxy