首页 > 解决方案 > 根据条件向数组添加其他对象

问题描述

我正在尝试对以下对象数组进行排序:

var input = [
          { name: 'Trevor Hansen', group: 'Group 1' },
          { name: 'Britta Holt', group: 'Group 2' },
          { name: 'Jane Smith ', group: 'Group 2' },
          { name: 'Sandra Adams', group: 'Group 1' },
          { name: 'Ali Connors', group: 'Group 1' },
          { name: 'John Smith', group: 'Group 2' },
          { name: 'Sandra Williams', group: 'Group 2' },
          { name: 'Tucker Smith', group: 'Group 1' },
        ],

这应该是结果:

var result = [
          { header: 'Group 1' },
          { name: 'Sandra Adams', group: 'Group 1' },
          { name: 'Ali Connors', group: 'Group 1' },
          { name: 'Trevor Hansen', group: 'Group 1' },
          { name: 'Tucker Smith', group: 'Group 1' },
          { divider: true },
          { header: 'Group 2' },
          { name: 'Britta Holt', group: 'Group 2' },
          { name: 'Jane Smith ', group: 'Group 2' },
          { name: 'John Smith', group: 'Group 2' },
          { name: 'Sandra Williams', group: 'Group 2' },
        ],

对数组进行排序后,需要在每个组之前添加一个标题对象,然后在组之间添加一个分隔对象,但在新标题之前。

这是我当前的代码,用于对数组进行排序:

function compare(a, b) {
        const valueA = a.group.toUpperCase();
        const valueB = b.group.toUpperCase();

        let comparison = 0;
        if (valueA > valueB) {
          comparison = 1;
        } else if (valueA < valueB) {
          comparison = -1;
        }
        return comparison;
      }

array.sort(compare);

但是,如何在必要时在正确的位置添加标题和分隔符?

很感谢任何形式的帮助!

标签: javascriptarraysobject

解决方案


我会用两个reduce()链接在一起来解决它。

const input = [{
    name: 'Trevor Hansen',
    group: 'Group 1'
  },
  {
    name: 'Britta Holt',
    group: 'Group 2'
  },
  {
    name: 'Jane Smith ',
    group: 'Group 2'
  },
  {
    name: 'Sandra Adams',
    group: 'Group 1'
  },
  {
    name: 'Ali Connors',
    group: 'Group 1'
  },
  {
    name: 'John Smith',
    group: 'Group 2'
  },
  {
    name: 'Sandra Williams',
    group: 'Group 2'
  },
  {
    name: 'Tucker Smith',
    group: 'Group 1'
  },
]


const groupItems = (arr) => {
  return arr.reduce((a, c) => {
    if (typeof a[c.group] === "undefined") a[c.group] = []
    a[c.group] = [...a[c.group], c]
    return a
  }, {})
}

const step1 = groupItems(input)

console.log(step1)

const insertHeaders = (obj) => {
  return Object.entries(obj).reduce((a, [key, vals], i, d) => {
    let r = [{
        header: key
      },
      ...vals,
    ]
    // this is needed to have the exact same array
    // that you presented as desirable output:
    // no divider at the last place
    if (i < d.length - 1) {
      r = [...r, {
        divider: true
      }]
    }
    a = [...a, ...r]
    return a
  }, [])
}

const step2 = insertHeaders(step1)
console.log(step2)

此解决方案的好处是您不需要了解有关输入的任何信息,只需知道它有一个attribute命名的group. 其他一切都是自动的:

  • 组是根据group属性创建的
  • 项目放置在标题之后和分隔符之前(最后一组除外 - 最后没有分隔符)

但这给我带来了一个问题:你为什么要创造array这样的作品?在大多数情况下,以这种方式使用数组并不是最好的主意。组很容易用 表示object,并且有一些函数可以迭代object( for...inObject.entries等)。如果您在 UI 中需要“标题”(例如表格元素等),最好将标题插入移动到代码的显示部分(与实际数据分离)并且仅在您创建视觉效果时应用。(当然:对你的情况不太了解,这个解决方案可能是完全明智的。:))


推荐阅读