数据扁平化-关联数组 (Associative Array)-Record(ts)

下方数据结构可以被描述为一个JavaScript对象(Object),其中每个键是一个UUID(Universally Unique Identifier),值是一个待办事项对象。
在编程和数据结构领域,这种组织形式没有一个特定的官方名称,但它通常被称为“字典”、“映射”、“关联数组”或“哈希表”。

  • 字典 (Dictionary):在Python等语言中常这样称呼,它存储键值对,并支持通过键高效查找对应的值。
  • 映射 (Map):在许多现代编程语言如Java、C++ STL中称为映射或HashMap。
  • 关联数组 (Associative Array):这个术语强调的是可以通过任意类型的键来索引数组元素,而不是仅仅通过整数索引。
  • 哈希表 (Hash Table):底层实现机制上,这种数据结构经常使用哈希函数将键转化为数组索引以实现快速访问。

在JavaScript中,虽然不直接叫哈希表,但其对象(Object)类型本质上提供了类似哈希表的功能。

 todos: {
      '82471c5f-4207-4b1d-abcb-b98547e01a3e': {
        id: '82471c5f-4207-4b1d-abcb-b98547e01a3e',
        title: 'Learn Zustand',
        done: false,
      },
      '354ee16c-bfdd-44d3-afa9-e93679bda367': {
        id: '354ee16c-bfdd-44d3-afa9-e93679bda367',
        title: 'Learn Jotai',
        done: false,
      },
      '771c85c5-46ea-4a11-8fed-36cc2c7be344': {
        id: '771c85c5-46ea-4a11-8fed-36cc2c7be344',
        title: 'Learn Valtio',
        done: false,
      },
      '363a4bac-083f-47f7-a0a2-aeeee153a99c': {
        id: '363a4bac-083f-47f7-a0a2-aeeee153a99c',
        title: 'Learn Signals',
        done: false,
      },
    },

这种结构的好处是什么?

这种数据结构的好处主要体现在以下几个方面:

  1. 唯一标识
    每个待办事项都有一个唯一的ID,如 '82471c5f-4207-4b1d-abcb-b98547e01a3e'。这使得在处理大量数据时,可以轻松地通过ID来定位、更新或删除特定的待办事项,而无需遍历整个数组或其他复杂操作。

  2. 易扩展性
    以键值对(key-value)的形式存储待办事项,当需要添加新的待办事项时,只需要生成一个新的唯一ID作为键,并创建一个新的待办对象即可。这种结构方便进行增删改查等操作。

  3. 高效的查询和更新
    在JavaScript环境中,根据键查找值是非常快速的操作,这意味着可以根据ID迅速找到并修改某个待办项的状态(例如:改变 done 的值)。

  4. 有序与无序
    这种结构并不依赖于待办事项的插入顺序,因此它们可以按任意顺序显示或操作,同时又能够保证每个待办事项在数据结构中的独立性。

  5. 符合数据库设计原则
    类似的数据结构常见于关系型数据库的设计中,其中主键用于唯一标识记录,其他字段则包含该记录的具体信息。这种方式有助于实现良好的数据一致性与完整性。

  6. 便于状态管理库使用
    在React状态管理库如Zustand、Jotai、Valtio或Signals中,这样的数据结构非常适合用来表示和管理状态,因为这些库通常支持基于键的读写操作,可以直接映射到这种结构上。

如何快速将一个数组转为上述结构?

假设你有一个数组,其中每个元素是一个包含id和其它属性的对象,要将它转换为上述键值对结构的JavaScript对象,可以使用.reduce()方法:

// 假设你的数组如下:
const todosArray = [
  {
    id: '82471c5f-4207-4b1d-abcb-b98547e01a3e',
    title: 'Learn Zustand',
    done: false,
  },
  // 其他待办事项...
];

// 使用 reduce 方法将其转换为键值对结构
const todosObject = todosArray.reduce((acc, todo) => {
  acc[todo.id] = todo;
  return acc;
}, {});

console.log(todosObject);

在这个例子中,.reduce()函数接收两个参数:一个累积器(accumulator)和当前项(currentValue)。
累积器在每次迭代时都会被更新,并在下一次迭代中作为累积器传入。初始值是一个空对象 {}

通过这种方式,我们遍历数组并将每个待办事项对象以其 id 作为键添加到新对象中。最后返回的就是一个以ID为键、待办事项为值的JavaScript对象。

有没有三方库可以快速实现上述转换

对于将数组转换为键值对对象这种简单的操作,通常不需要专门的第三方库。
JavaScript内置的reduce()方法已经足够高效和方便。
不过,如果你正在使用一些功能丰富的数据处理库如Lodash或Ramda,它们也提供了相应的便捷函数可以完成这个任务。

例如,在Lodash中,可以使用_.keyBy()方法:

import _ from 'lodash';

const todosArray = [
  // ...
];

const todosObject = _.keyBy(todosArray, 'id');

在Ramda中,可以组合使用R.indexBy()R.prop()方法:

import R from 'ramda';

const todosArray = [
  // ...
];

const todosObject = R.indexBy(R.prop('id'), todosArray);

但总的来说,直接使用原生JavaScript的reduce()方法是最简洁且无需额外依赖的方式。

posted @ 2024-03-02 23:42  龙陌  阅读(87)  评论(0)    收藏  举报