JavaScript如何从数组中删除特定数据

Posted 程序员半夏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript如何从数组中删除特定数据相关的知识,希望对你有一定的参考价值。

增删改查是我们日常开发中的最基本任务,在javascript中我们经常需要从数据组删除特定的数据项。然而,JavaScript数组中并没有提供删除特定数据项的方法。所以我们必须使用替代的方法,来从javaScript中删除特定数据项。

1:使用 filter()

使用现代 Javascript 删除特定数组项的最简单方法是使用过滤器。让我们看一个简单的例子:

let myArr = [ "🍎", "🍏", "🍐", "🍍" ];


let removedArr = myArr.filter((x) => x !== "🍍");
console.log(removedArr);

当我们的数组中的每一个数据想都是唯一的时候,他是正常工作的,但是当我们的存在重复项的时候,此时如果你只想删除一个,保留其他重复的,这种方式是无法做到的。

let myArr = [ "🍎", "🍏", "🍏", "🍍" ];


let removedArr = myArr.filter((x) => x !== "🍏");
console.log(removedArr);

由于我们有两个青苹果,并且新数组过滤掉了所有青苹果,因此我们在使用此方法时实际上删除了两个项目。如果我们只想删除一个元素,我们必须使用另一种方法。

2:使用 indexOf() 和 splice()

indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。如果没有找到匹配的字符串则返回 -1。
splice() 方法用于添加或删除数组中的元素。注意:这种方法会改变原始数组。
这种方式与上面的区别在于:

  1. 首先,它改变了原始数组——所以我们不在这里复制。原始数组将被改变。
  2. 其次,它使用两个函数——首先我们获取indexOf要删除的数组项,然后我们splice获取数组以删除单个项。

这是一个例子:

let myArr = [ "🍎", "🍏", "🍏", "🍍" ];
let getLocation = myArr.indexOf("🍏");
myArr.splice(getLocation, 1);
// myArr now becomes [ "🍎", "🍏",  "🍍" ];
console.log(myArr);

结论

尽管在 Javascript 中没有直接从数组中删除项目的方法,但我们确实有两个工具可以为我们提供足够的灵活性来涵盖几乎所有有关删除数组项目的场景。

如何从数组中删除特定对象? [复制]

【中文标题】如何从数组中删除特定对象? [复制]【英文标题】:How to remove specific object from array? [duplicate] 【发布时间】:2017-04-08 14:55:04 【问题描述】:

如果调用者传入一个 MyDelegate 类型的对象并且它在数组中,我想将它从数组中移除。

protocol MyDelegate 


private var delegates = [MyDelegate]()
...
...
func removeDelegate(_ delegate: MyDelegate) 
    if let index = self.delegates.index(where:  $0 == delegate ) 
        log.trace("Removing delegate \(delegate)");
        self.delegates.remove(at: index)
    

    有没有更简单的方法来做到这一点?

    此条件“ $0 == delegate ”导致错误“无法将类型 '(OptionalNilComparisonType) -> Bool' 的值转换为预期的参数类型 '( ) -> 布尔'"。我怎样才能解决这个问题?我试过添加?和 !但仍然没有完全理解 Swift 的可选概念。

我正在使用 Xcode 8.2.1 和 Swift 3(?)。

【问题讨论】:

代理应该是类的实例吗? 然后你可以定义一个“类协议”protocol MyDelegate: class 并使用身份运算符进行比较:index(where: $0 === delegate ) 【参考方案1】:
    有没有更简单的方法来做到这一点?

可以在访问delegates 成员时忽略self,并将index(where:) 调用的结果索引烘焙到对Optionalmap 方法的调用中:

func removeDelegate(_ delegate: MyDelegate) 
    delegates.index(where:  $0 == delegate)
        .map  delegates.remove(at: $0) 

如果没有找到这样的delegate 对象,则上面的表达式只会返回nil(未捕获的结果)。


这个条件“ $0 == delegate ”给出导致错误, “无法将 '(OptionalNilComparisonType) -> Bool' 类型的值转换为 预期的参数类型'() -> Bool'”。我该如何解决这个问题?我试过了 添加?!,但仍不能完全理解Swift 的可选 概念。

这是 Swift 中一种模糊错误消息的又一个例子。核心错误是MyDelegate没有定义==操作符(不符合Equatable)。

但是,在您进行编辑后,您显示MyDelegate 是一个协议,因此如果您让它符合Equatable,您将无法(因为它将包含Self 类型要求)使用@ 987654345@ 作为具体类型(仅作为泛型上的类型约束)。

如果您的具体委托对象是引用对象 (class),并且您想在测试的意义上测试对象相等性是否都引用同一个对象(对象引用),您可以使用 @987654321 @ 可用于类实例。将MyDelegate(在您的编辑后将其显示为协议)限制为仅类,

protocol MyDelegate: class  /* ... */ 

并在上面的index(where:) 调用中测试ObjectIdentifier 的相等性:

func removeDelegate(_ delegate: MyDelegate) 
    delegates.index(where:  ObjectIdentifier($0) == ObjectIdentifier(delegate) )
        .map  delegates.remove(at: $0) 

查看ObjectIdentifier 的源代码,我们看到这将比较两个delegate 实例的底层原始ptr 值;来自swift/stdlib/public/core/ObjectIdentifier.swift:

public static func == (x: ObjectIdentifier, y: ObjectIdentifier) -> Bool 
  return Bool(Builtin.cmp_eq_RawPointer(x._value, y._value))


正如@MartinR 在上述问题的 cmets 中所提到的,您也可以直接将 === 标识运算符用于类实例,而不是通过 ObjectIdentifier

func removeDelegate(_ delegate: MyDelegate) 
    delegates.index(where:  $0 === delegate )
        .map  delegates.remove(at: $0) 

为了完整起见,我们可以通过查看swift/stdlib/public/core/Equatable.swift 来验证=== 使用与== 运算符相同的Builtin 方法ObjectIdentifier

public func === (lhs: AnyObject?, rhs: AnyObject?) -> Bool 
  switch (lhs, rhs) 
  case let (l?, r?):
    return Bool(Builtin.cmp_eq_RawPointer(
        Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(l)),
        Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(r))
      ))
  case (nil, nil):
    return true
  default:
    return false
  

【讨论】:

没有像 java 和 c# 中的默认对象相等的 Swift 概念吗? @RichAmberale 一般来说,没有。 Object​Identifier 可用于类实例,因此如果您将 MyDelegate (在编辑后将其显示为协议)限制为仅类,您可以测试 ObjectIdentifier:s 的 $0 的相等性和上面的delegate。这实质上是测试两者是否引用(对象引用)到同一个对象,而不是在某些预定义的== 运算符的意义上它们是否相等。 @MartinR 感谢您的链接!我在ObjectIdentifier 的源代码中看到了相同的评论部分,但正在四处寻找=== 的实际实现(以验证它很可能调用相同的Builtin 方法)。 @RichAmberale 乐于提供帮助。这可能是个人喜好,但我自己在使用 Swift 时通常会避免使用 Obj-C 功能,所以我自己可能更喜欢 === / ObjectIdentifier 而不是 NSObjectProtocol:s isEqual(...) 方法。跨度> 感谢您的链接,我已经更新了其他答案。 - 我不知道。从github.com/apple/swift/blob/master/include/swift/AST/… 看来,似乎没有必要:“CastToUnknownObject 具有类型 (T) -> Builtin.UnknownObject。”和“BridgeToRawPointer 具有类型 (T) -> Builtin.RawPointer”——但我对“内置 SIL 操作”没有更深入的了解 :)

以上是关于JavaScript如何从数组中删除特定数据的主要内容,如果未能解决你的问题,请参考以下文章

如何从javascript或jquery中的元素数组中删除特定元素

如何从GoogleMapsAPI中的静态数组中删除特定标记

使用jquery表中的复选框从数组中删除JavaScript对象

如何从 javascript 变量中删除对象/数组?

当数组达到特定长度时删除javascript数组的最后一个元素

如何使用jQuery从数组中删除特定值