【问题标题】:Javascript Map a CollectionJavascript 映射集合
【发布时间】:2018-07-22 19:31:53
【问题描述】:

问题:

我正在尝试构建一个简单的搜索工具。它通过将 id 与具有相同 id 的另一个项目匹配来返回搜索查询。在不涉及复杂性的情况下,我遇到的问题是,当我之前组织我的数据时,来自 javascript 的 map 函数完美地返回了所有结果。但是,现在我的数据结构有点不同(我认为是一个集合?)......id 似乎没有排列,这会导致显示错误的搜索结果。

有问题的函数:

const options = this.props.itemIds.map((id) => (
  <Option key={this.props.itemSearchList[id].id}>
     {this.props.itemSearchList[id].name}
  </Option>
));

当数据的结构像这样时,它按预期工作:

以前的结构示例:

const items = [
  {
    id: 0,
    name: "name 0",
    tags: ['#sports', '#outdoor', '#clothing'],
  },
  {
    id: 1,
    name: "name 1",
    tags: ['#sports', '#outdoor', '#clothing'],
  },
  {
    id: 2,
    name: "Name 2",
    tags: ['#sports', '#outdoor', '#clothing'],
  },

现在数据是一个 ?collection...map 函数没有按预期工作,它返回不正确的结果或根本没有:我已经能够使用 lodash Map过去成功地在这个结构上运行。

这是新数据的截图:

我认为写出示例的代表性方式是:

const newItems = [
  0: {
    id: 0,
    name: "name here",
  },
  1: {
    id: 1,
    name: "name here",
  },
]

对这项工作有何建议或需要更多信息?也许我完全误解了这个问题,但我相信它与 JS 的数据结构和 map 函数有关。我可以看到结果返回,但 id 不再正确排列。

这是错位的直观表示。橙色是搜索输入,它会拉出正确的结果。由于数据结构和映射(我假设),绿色是它实际显示的错位。

【问题讨论】:

  • 您的newItems 示例不起作用。 JavaScript 中不能有键值对数组。
  • 在 newItems 之后使用 [ 而不是 {
  • @charlie 可能造成了整个混乱,因为 OP 向我们提供了他的控制台显示的内容,这不是有效的 JSON(但人们仍然可以理解 IMO)
  • 我认为令人困惑的是您正在查看网络工具,看到这些数字并假设它是不同的形状,由数字或其他东西键入。它不是。这只是您的浏览器友好的方式,可以向您显示每个元素所在的索引,但它仍然与 items 完全相同的数组。
  • 错误解释了“新数据的屏幕截图”。它是一个对象数组。它被显示为带有数组索引的单个数组元素的标签。这不是结构本身的一部分。而且,[1] 显示“id”而其他没有,所以我想知道对象的成员是否一致。

标签: javascript collections


【解决方案1】:

所谓的“集合”和“地图”实际上是数组。现在,其中一个数组的对象恰好位于数组中与 id 匹配的位置:

items[5].id === 5

现在通过排序 /mutating / 无论您更改顺序,以便某个位置的元素没有它作为 id:

newItems[5].id // 7 :(

这意味着您不能再那么容易地访问该项目,您现在要么必须再次对数组进行排序以使其有序,要么搜索具有 id 的对象:

newItems.find(item => item.id === 5) // { id: 5, ... }

或者你切换到一些未排序的集合,比如真正的Map

const itemsMap = new Map(newItems.map(item => ([item.id, item])));

所以你可以得到一个特定的项目,其 id 为:

itemsMap.get(5) // { id: 5, ... }

...但整件事与Array.prototype.map 完全无关。

【讨论】:

    【解决方案2】:

    问题是您正在使用索引并将其与 id 对齐作为一种伪键,它......超出了脆弱性。你应该做的通过 id 键控(意思是items应该是一个对象),然后有一个单独的数组来存储你想要的顺序。所以items 将是一个以 id 为键的对象:

    const items = {
      1: {
        id: 1,
        name: "name 1",
        tags: ['#sports', '#outdoor', '#clothing'],
      },
      2: {
        id: 2,
        name: "name 2",
        tags: ['#sports', '#outdoor', '#clothing'],
      },
      9: {
        id: 9,
        name: "Name 9",
        tags: ['#sports', '#outdoor', '#clothing'],
      },
    };
    

    然后itemIds(您似乎已经拥有)是一个具有正确顺序的数组:

    const itemIds = [1,9,2];
    

    然后可以通过遍历该数组以正确的顺序访问它们,并通过所述键获取元素:

    itemIds.map((id) => {
      const item = items[id];
      // do something with the item
    }
    

    看看 Redux 是如何推荐规范化状态形状的。

    https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape

    【讨论】:

      【解决方案3】:

      这是我的简单解决方案:

      const options = [];
          this.props.itemList.forEach((item) => {
            if (this.props.searchResults.includes(item.id)) {
              options.push(<Option key={item.id}>{item.name}</Option>);
            }
          });
      

      让我知道您的想法(向试图提供帮助的小组!)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-10
        • 2018-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-27
        • 2021-12-09
        相关资源
        最近更新 更多