【问题标题】:Replace properties of specific elements in object替换对象中特定元素的属性
【发布时间】:2020-08-09 23:03:52
【问题描述】:

这是数据:

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 中对象的顺序。 谢谢。

【问题讨论】:

标签: javascript sorting object


【解决方案1】:

我认为您可以在 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 开始,几乎所有这些函数(groupByminBy 除外)都可以在 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)

【讨论】:

    【解决方案2】:

    使用 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-30
      • 2020-03-27
      • 1970-01-01
      相关资源
      最近更新 更多