【问题标题】:Swift Filter Nested ArraySwift 过滤器嵌套数组
【发布时间】:2017-01-28 10:55:12
【问题描述】:

我有一个NSMutableArray,它自己里面有很多数组。在所有索引处的每个数组中,它们还具有下面给出的类的自定义对象。

Class User:NSObject{
    var name = ""
    var userName = ""
    var email = ""
    var age = 0
    var gender = ""
    var 
}

我想针对两个对象过滤这个嵌套数组。 例如,如果用户在 searchBar 中键入一些文本并检查该嵌套数组中的文本,如果该文本与名称或用户名或两者匹配。

【问题讨论】:

  • 您要保留嵌套层次结构还是返回一个扁平的 [User] 数组?
  • 我想保留嵌套层次结构,这是我目前无法解决的问题。

标签: ios swift nsmutablearray


【解决方案1】:
let textToSearch:String = "some text"

for nestedArray in myArray {

    for item:User in nestedArray
    {
        if user.name.contains(textToSearch) || user.userName.contains(textToSearch)
        {
            print("found")
        }
    }

}

【讨论】:

  • 这个方法会在字符串内的任意随机范围内搜索文本吗?例如,如果字符串包含“这是要搜索的神秘字符串”并且用户刚刚输入“tica”,此方法是否会成功在上述字符串中搜索此字符串?
  • 是的,它在整个字符串中搜索所有范围,如果匹配则返回 true。因此,通过您的示例,它会找到文本。另一个例子是名称是“Mark Blogs”,您搜索“log”就会找到它。
  • 哦..谢谢先生。非常感谢您的帮助。
【解决方案2】:

这是使用Array 提供的filter(_:) 方法的更“快速”的方法。

方法:

func filter(_ isIncluded: (Element) throws -> Bool) rethrows -> [Element]

实施:

    // Create some generic objects to test on
    let object1 = User()
    object1.name = "John"
    object1.userName = "jdoe"

    let object2 = User()
    object2.name = "Jane"
    object2.userName = "jdoe"

    let object3 = User()
    object3.name = "Bob"
    object3.userName = "bjones"

    // Add them to a test array
    var objects = [[]]
    objects.append([object1])
    objects.append([object2])
    objects.append([object3])

    // What we want to search on
    let searchString = "j"

    // Filter the array
    for array in objects {
        let searchedSubArray = array.filter {
            return $0.name.rangeOfString(searchString, options: .CaseInsensitiveSearch)     != nil ||
                   $0.userName.rangeOfString(searchString, options: .CaseInsensitiveSearch) != nil

        }
        if (searchedSubArray.count > 0) {
            print("we found a match!")
        }
    }

【讨论】:

    【解决方案3】:
    let nestedArray: [[User]] = [[user1, user2], [user3], [user4, user5]]
    
    let searchName = "foo"
    let filteredArray = nestedArray.map({
            return $0.filter({ $0.name == searchName })
        }).filter({ $0.count > 0 })
    

    这是一种纯粹的函数式方法,它会生成一个新的嵌套数组,该数组只包含匹配用户的数组,并且这些数组也只会包含匹配的用户。

    【讨论】:

      【解决方案4】:

      一些建议

      结构更适合模型值

      struct User {
          let name: String
          let userName: String
          let email: String
          let age: Int
          let gender: String
      }
      

      不要使用 NSMutableArray

      ​​>

      NSMutableArray 是一个 Objective-C 类。您可以通过 Swift 访问它,但您应该使用 Swift 数组结构。它速度更快,并且作为一种值类型,可以防止与代码的多个部分访问共享对象相关的错误。

      过滤您的数据

      现在给出User的数组数组

      let data: [[User]] = ...
      

      还有一个关键字

      let keyword: String = ...
      

      你可以过滤你的数据写入

      let matchingUsers = data
          .flatMap { $0 }
          .filter { $0.name.range(of: keyword) != nil || $0.userName.range(of: keyword) != nil }
      

      现在matchingUsersUser(s) 的数组,其中nameusername 包含keyword

      【讨论】:

      • 所以我理解得更好了,你是在打电话给.filter.flatMap { $0 } 返回什么吗?
      • @random: YESflatMap的输出由filter处理
      • 我明白了。然后过滤器返回符合条件的Users,暗示-> Bool
      • @random:顺便说一句,我的代码有错误,现在已经修复了。
      【解决方案5】:

      matteok 建议的稍微改进的版本:

      在这种过滤中忽略寄存器是有意义的,而不是检查相等性检查查找目标是否包含搜索查询

      另外使用!$0.isEmpty 比检查$0.count > 0 更快捷

      let nestedArray: [[User]] = [[user1, user2], [user3], [user4, user5]]
      
      let searchName = "foo".lowercased()
      let filteredArray = nestedArray
        .map { $0.filter { $0.name.lowercased().contains(searchName) }}
        .filter { !$0.isEmpty }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-19
        • 1970-01-01
        • 2022-08-19
        • 1970-01-01
        • 2021-08-26
        • 1970-01-01
        • 2023-01-28
        • 1970-01-01
        相关资源
        最近更新 更多