Заменить свойства указанных c элементов в объекте - PullRequest
0 голосов
/ 26 апреля 2020

вот данные:

const data = {
  element6: {
    col: 2,
    row: 3,
    text: "Col2, Row1"
  },
  element1: {
    col: 1,
    row: 1,
    text: "Col1, Row1"
  },
  element8: {
    col: 3,
    row: 2,
    text: "Col2, Row1"
  },
  element2: {
    col: 1,
    row: 2,
    text: "Col1, Row2"
  },
  element5: {
    col: 2,
    row: 2,
    text: "Col2, Row2"
  },
  element3: {
    col: 1,
    row: 3,
    text: "Col1, Row3"
  },
  element4: {
    col: 2,
    row: 1,
    text: "Col2, Row1"
  },
   element7: {
    col: 3,
    row: 1,
    text: "Col2, Row1"
  },
   element9: {
    col: 3,
    row: 3,
    text: "Col2, Row1"
  },

};

Я хочу добавить свойство ind (равное значению col элемента) и перезаписать col (наименьшее значение) выбранным) ко всем элементам, которые находятся в одном и том же row и различаются col. Например, elements 2, 5 и 8 находятся в row: 2, поэтому они изменятся на:

{
  element8: {
    col: 1,
    row: 2,
    text: "Col2, Row1",
    ind: 3
  },
   element2: {
    col: 1,
    row: 2,
    text: "Col1, Row2",
    ind: 1
  },
    element5: {
    col: 1,
    row: 2,
    text: "Col2, Row2",
    ind: 2
  },
}

Обратите внимание, я не хочу изменять порядок объектов в data. Спасибо.

Ответы [ 2 ]

0 голосов
/ 26 апреля 2020

Я думаю, что вы можете сделать это с помощью lodash (или любой другой вспомогательной библиотеки). Предполагая, что ваш data является объектом (кстати, порядок ключей в объекте не гарантирован!)

    const res = _.chain(data)
        .toPairs()
        .groupBy(([key, val]) => val.row)
        .mapValues(list => {
            const smallestCol = _.minBy(list, ([key, val]) => val.col)[1].col
            return list.map(([key, val]) => [key, {...val, ind: val.col, col: smallestCol}])
        })
        .values()
        .flatten()
        .fromPairs()
        .value();

Возможно, стоит отметить, что начиная с ES2019 почти все эти функции (за исключением groupBy и minBy) доступны в стандартной библиотеке JS, хотя они не так хорошо сцепляются

    function groupBy(array, selector) {
        return array.reduce((res,curr) => {
            const key = selector(curr)
            if({}.hasOwnProperty.call(res, key)) {
                res[key].push(curr)
            } else {
                res[key] = [curr]
            }
            return res
        }, {})
    }
    function minBy(array, selector) {
        return Math.min(...array.map(selector))
    }
    const groupedbyRow = groupBy(Object.entries(data), ([key, element]) => element.row)
    const remappedValues = Object.values(groupedbyRow).flatMap(list => {
        const smallestCol = minBy(list, ([key, val]) => val.col)
        return list.map(([key, val]) => [key, {...val, ind: val.col, col: smallestCol}])
    })
    const res = Object.fromEntries(remappedValues)
0 голосов
/ 26 апреля 2020

Используйте итерацию оператора for ... in, как @Ravenous упомянул

const smallColl = currentRow => {
  let small;

  for (let key in data) {
    const { col, row } = data[key];

    if (row !== currentRow) continue;

    if (!small || col < small) small = col;
  }

  return small;
};

// another method
const smallColl = currentRow =>
  Math.min(
    ...Object.values(data)
      .filter(({ row }) => row === currentRow)
      .map(({ col }) => col)
  );

for (let key in data) {
  const { col, row } = data[key];
  data[key].ind = col;
  data[key].col = smallColl(row);
}

для повышения производительности, используйте памятку:

for (let key in data) {
  const colMin = {};

  const { col, row } = data[key];
  data[key].ind = col;

  const min = colMin[row] || smallColl(row);

  data[key].col = min;

  if (colMin[row]) colMin[row] = min;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...