【问题标题】:Javascript Array Splice without changing the indexJavascript Array Splice 不改变索引
【发布时间】:2013-06-27 13:50:20
【问题描述】:

我正在进行聊天并使用数组来保存用户。这是我的问题:

User1 加入并通过推送获得数组中的索引 0。 User2 加入并通过 push 获得数组中的索引 1。

User1 断开连接并通过拼接移除。

现在 User2 变为索引 0。

User1 重新连接并通过推送获得索引 1。

User2 断开连接,索引 1 被删除,现在是 User1。

这当然会引起问题。

所以我的问题是如何在不改变其他元素索引的情况下从数组中删除项目?我是不是走错了路?

【问题讨论】:

  • 只需将该字段设置为空
  • “这当然会造成问题。” - 为什么是“当然”?这可能是完全可以接受的,具体取决于您的其他代码如何使用数组。 (也就是说,您的其他代码可以以不依赖于数组索引的方式编写。)话虽如此,您可以使用对象而不是数组...

标签: javascript arrays indexing


【解决方案1】:

为什么不直接将值设置为nullundefined,而不是使用splice() 从数组中删除项目?

然后,当您添加新用户时,您只需扫描数组即可找到第一个可用插槽。

javascript 数组只是项目的列表——它们并不像您在 PHP 中所熟悉的那样与特定的键绑定。因此,如果您想在数组中保持相同的位置,则不能删除其他项目 - 您需要保留它们,并将它们标记为空。


您可能会浏览以下内容:

var users = [];
function addUser(user) {
    var id = users.indexOf(null);
    if (id > -1) {
        // found an empty slot - use that
        users[id] = user;
        return id;
    } else {
        // no empty slots found, add to the end and return the index
        users.push(user);
        return users.length - 1;
    }
}
function removeUser(id) {
    users[id] = null;
}

【讨论】:

  • 感谢您的回复。我曾考虑使用删除,因为它比让每个新用户都增长索引并且让​​索引增长得非常大要好。您能否解释一下如何“扫描”并找到然后将其分配给数组。更准确地说,如何扫描,如果可用则分配,如果没有则推送到最后?
  • 假设您通过将插槽设置​​为null 来“清除”一个插槽,您可以使用yourArray.indexOf(null) 获取第一个可用插槽的索引。如果它返回-1,这意味着没有空条目,那么你可以.push()
  • @nnnnnn 谢谢,我忽略了这一点。我更新了我的示例以使用indexOf
【解决方案2】:

使用delete 代替splice

> a = ['1', '2', '3']
< Array [ "1", "2", "3" ]

> delete a[1]
< true

> a
< Array [ "1", undefined × 1, "3" ]

> a.length
< 3

【讨论】:

  • a.filter(x=&gt;x).length 将给出长度为 2
  • 我认为这是意料之中的,正如问题所问的那样:> 如何在不改变其他元素索引的情况下从数组中删除项目
  • 是的,我只是想添加它作为获取非空索引长度的一种方式。
  • 抱歉,我看错了。 :) 是的,确实可以获得已定义元素的长度。 :)
【解决方案3】:

另一种选择是使用 javascript 对象而不是数组。

类似这样的:

var users = {};

users[1] = 'user 1';
users[2] = 'user 2';

delete users[1];
alert(users[2]);        // alerts "user 2"
alert(typeof users[1]); // alerts "undefined"

您丢失了数组 length 属性,因此您必须自己跟踪最大用户数。

【讨论】:

    【解决方案4】:

    我确信有多种解决方案可以根据您的具体情况发挥作用。我有一个使用 React 的项目,并且在将数组中的对象设置为未定义时遇到了类似的问题,因为在代码的其他地方我会收到类似 cannot find {key} of undefined 的错误...null 也发生了同样的情况...我的解决方案现在可以正常工作的方法是简单地重新创建整个数组,在我的情况下我可以这样做,因为它不是一个超长的列表。已更改以符合您的描述:

    let newUsers = [];
    users.forEach((u, i) => {
      if (u.isOnline) newUsers[i] = u;
    });
    this.setState({ users: newUsers });
    

    ...类似的东西。就我而言,我有一个选定食谱的列表。如果食谱从食谱的整体列表中删除,这会将其从选择列表中删除,其中选定的索引指示它是哪个“课程”(即开胃菜、主菜、甜点),因此索引很重要。

    另一种解决方案是使用您的用户 ID 作为数组的索引。当用户上线时可以设置onlineUsers[user.ID] = user //or true or user.Name or whatever

    【讨论】:

      【解决方案5】:

      删除数组元素而不面临重新索引问题

          var ind=[1,6]; //index positions of elements to remove
          var arr=['a','b','c','d','e','f','g']; // actual array
          var arr2 = arr.filter(function(item,index){
                  if(ind.indexOf(index)== -1){
                  return true;
          }});
      

      现在 arr2 是 ==========>> ['a','c','d','e','f']

      【讨论】:

      • 这怎么没有改变索引? c 移动到索引 1,它应该保持在 2,除非我误解了 OP 问题。
      猜你喜欢
      • 2014-12-09
      • 1970-01-01
      • 1970-01-01
      • 2011-07-08
      • 2011-01-04
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多