преобразовать массив объектов во вложенный массив массивов для построения диаграммы - PullRequest
1 голос
/ 02 февраля 2020

У меня есть следующий массив

const data = [
      {
        date: "2018-01-01",
        label: "MH",
        qt: 10
      },
      {
        date: "2018-04-01",
        label: "MH",
        qt: 30
      },
      {
        date: "2018-02-01",
        label: "GJ",
        qt: 30
      },
      {
        date: "2018-03-01",
        label: "KL",
        qt: 30
      },
      {
        date: "2018-02-01",
        label: "KL",
        qt: 40
      }
    ]

, и я хочу, чтобы мой вывод был

[
  [date,MH,GJ,KL],
  ['Jan 2018',10,null,null],
  ['Feb 2018',null,30,40],
  ['Mar 2018',null,null,30],
  ['Apr 2018',30,null,null]
]

Как я могу добиться этого оптимизированным способом? И дата должна быть отсортирована для того, чтобы. Я пытался сделать

data.sort(function compare(a, b) {
      var dateA = new Date(a.date);
      var dateB = new Date(b.date);
      return dateA - dateB;
    });
    let labelArr = data.map(l => l.label);
    let dateArr = data.map(l => l.date);
    labelArr = _.uniq(labelArr);
    dateArr = _.uniq(dateArr);
    console.log(labelArr, dateArr);

    const outputArr = [];
    dateArr.forEach(d => {
      labelArr.forEach(l => {
        const tempObj = data.filter(r => {
          if (d == r.date && l == r.label) {
            return r;
          }
          else {
            return { date: d, label: l, qt: null }
          }
        })
        outputArr.push(tempObj);
      });
    });

, но я застрял здесь. Сначала я создам объекты для даты и метки, которых нет, и добавлю их qt к нулю. После этого я сгруппирую по дате, а затем вставлю только qt в результат

Ответы [ 3 ]

2 голосов
/ 02 февраля 2020

Вы можете взять объект для хранения массива для каждой даты и один для отслеживания индексов столбцов.

В конце установите все элементы на null для не заданных элементов.

var data = [{ date: "2018-01-01", label: "MH", qt: 10 }, { date: "2018-04-01", label: "MH", qt: 30 }, { date: "2018-02-01", label: "GJ", qt: 30 }, { date: "2018-03-01", label: "KL", qt: 30 }, { date: "2018-02-01", label: "KL", qt: 40 }],
    cols = {},
    rows = {},
    result = data
        .sort(({ date: a }, { date: b }) => a > b || -(a < b))
        .reduce((r, { date, label, qt }) => {
            date = date.slice(0, 7);
            if (!rows[date]) r.push(rows[date] = [date]);
            if (!cols[label]) cols[label] = r[0].push(label) - 1;
            rows[date][cols[label]] = (rows[date][cols[label]] || 0) + qt;
            return r;
        }, [['date']])
        .map((a, _, [{ length }]) => Array.from({ length }, (_, i) => a[i] || null));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 02 февраля 2020

Я не знаю, является ли это лучшим решением, но это рабочее решение:

const data = [{
    date: "2018-01-01",
    label: "MH",
    qt: 10
  },
  {
    date: "2018-04-01",
    label: "MH",
    qt: 30
  },
  {
    date: "2018-02-01",
    label: "GJ",
    qt: 30
  },
  {
    date: "2018-03-01",
    label: "KL",
    qt: 30
  },
  {
    date: "2018-02-01",
    label: "KL",
    qt: 40
  }
]

function formatData(data) {
  const labels = {};
  const map = {};
  
  data
    .sort((a, b) => a.date < b.date ? -1 : 1)
    .forEach(item => {
      const date = moment(item.date).format('MMM YYYY');
      labels[item.label] = true;
      if (map[date]) {
        map[date][item.label] = item.qt;
      } else {
        map[date] = { [item.label]: item.qt };
      }
    });

  const labelsArr = Object.keys(labels);
  const formattedData = Object.keys(map).map(date => {
    const values = labelsArr.map(label => map[date][label] || null);
    return [date, ...values];
  });
  
  return [['date', ...labelsArr], ...formattedData];
}

const result = formatData(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://momentjs.com/downloads/moment.min.js"></script>
0 голосов
/ 02 февраля 2020

Я пытался сделать это:

    data.sort(function compare(a, b) {
      var dateA = new Date(a.date);
      var dateB = new Date(b.date);
      return dateA - dateB;
    });
    let labelArr = data.map(l => l.label);
    let dateArr = data.map(l => l.date);
    labelArr = _.uniq(labelArr);
    dateArr = _.uniq(dateArr);

    const outputArr = [['Date', ...labelArr]];
    dateArr.forEach(d => {
      const o1 = data.filter(e => e.date == d)
      const o2 = o1.reduce((s, a) => {
        s[a.label] = a.qt;
        return s;
      }, {})
      const b1 = []
      labelArr.forEach(l => {
        b1.push(o2[l])
      });
      outputArr.push([moment(d).format('MMM YYYY'), ...b1]);
    });

Надеюсь, это кому-нибудь поможет.

...