Ios 使用内部数组详细信息筛选Swift数组
我有一个包含purchaseID、purchaseCategory的购买详细信息的数组列表。purchaseCategory是另一个字符串数组,详细说明该purchaseID下的产品。我正在尝试根据swift中purchaseCategory中的项目筛选主数组列表。下面是示例代码Ios 使用内部数组详细信息筛选Swift数组,ios,swift,filter,Ios,Swift,Filter,我有一个包含purchaseID、purchaseCategory的购买详细信息的数组列表。purchaseCategory是另一个字符串数组,详细说明该purchaseID下的产品。我正在尝试根据swift中purchaseCategory中的项目筛选主数组列表。下面是示例代码 let purchaseList = [["purchaseId":1 ,"purchaseCategory" : ["meatballs" ,"burger","cheese" ,"onions" , "apples
let purchaseList = [["purchaseId":1 ,"purchaseCategory" : ["meatballs" ,"burger","cheese" ,"onions" , "apples"]],["purchaseId":2 ,"purchaseCategory" : ["apple","orange" , "olive" , "cheese"]],["purchaseId":3,"purchaseCategory" : ["apple","orange" , "olive" , "cheese" , "Pepsi"]]]
我们如何筛选purchaseList以仅返回包含“olive”的详细信息purchaseCategory使用
筛选:
let purchaseList: [[String:AnyObject]] = [
["purchaseId":1 ,"purchaseCategory" : ["meatballs" ,"burger","cheese" ,"onions" , "apples"]],
["purchaseId":2 ,"purchaseCategory" : ["apple","orange" , "olive" , "cheese"]],
["purchaseId":3,"purchaseCategory" : ["apple","orange" , "olive" , "cheese" , "Pepsi"]]
]
func findCategoryContaining(word: String) -> [[String : AnyObject]] {
return purchaseList.filter {
if let arr = $0["purchaseCategory"] as? [String] {
return arr.contains(word)
}
return false
}
}
let result = findCategoryContaining("olive")
结果:
[[“采购ID”:2,“采购类别”:(
苹果,
橙色
奥利弗,
奶酪
)],[“采购ID”:3,“采购类别”:(
苹果,
橙色
奥利弗,
奶酪,
百事可乐
)]]
过滤器
功能可以做到这一点
let itemsContainingOlives = purchaseList.filter{ ($0["purchaseCategory"] as! [String]).contains("olive")}
安全通过过滤器的快捷方式:
purchaseList.filter { (element) -> Bool in
return (element["purchaseCategory"] as? [String])?.contains("olive") ?? false
}
请检查此代码,它对您有帮助
var purchaseCategory = NSMutableArray()
for item in purchaseList {
for (index, value) in item {
if index as! String == "purchaseCategory" {
if value.containsObject("olive") {
purchaseCategory.addObject(value)
}
}
}
}
// Output:
[["apple","orange" , "olive" , "cheese"],["apple","orange" , "olive" , "cheese" , "Pepsi"]]
因此,这里的其他答案涉及将内部字典的值强制转换为字符串。这很好,但是也许你应该考虑用不同的方式构造你的原始数据。您可以保留相同的信息,但使用类型安全,如下所示:
let purchaseList = [
1 : ["meatballs", "burger", "cheese", "onions", "apples"],
2 : ["apple", "orange", "olive", "cheese"],
3 : ["apple", "orange", "olive", "cheese", "Pepsi"]
]
purchaseList.filter { (_,v) in v.contains("olive") }
// [
// (2, ["apple", "orange", "olive", "cheese"]),
// (3, ["apple", "orange", "olive", "cheese", "Pepsi"])
// ]
你可以这样过滤它:
let purchaseList = [
1 : ["meatballs", "burger", "cheese", "onions", "apples"],
2 : ["apple", "orange", "olive", "cheese"],
3 : ["apple", "orange", "olive", "cheese", "Pepsi"]
]
purchaseList.filter { (_,v) in v.contains("olive") }
// [
// (2, ["apple", "orange", "olive", "cheese"]),
// (3, ["apple", "orange", "olive", "cheese", "Pepsi"])
// ]
另一种没有显式转换的方式
假设您将采购列表
作为[NSDictionary]
或[[String:AnyObject]]
:
let result = purchaseList.filter {
$0["purchaseCategory"]?.containsObject?("olive") == true
}
如果purchaseList
是[AnyObject]
,您可以:
let result = purchaseList.filter {
$0["purchaseCategory"]??.containsObject?("olive") == true
}
因为还没有足够的答案(7!),而且还没有人提到元组数组和集合,所以我也要给出我的输入:
如前所述,您可能需要一种更安全的方式来实现这一点(Swift是关于类型安全的!)。您编写数组的方式是JSON风格,其中所有内容都是字符串。一般来说,如果您想编写一流的Swift代码,请不要将用作
我最初的建议是使用由一个整数和一组字符串组成的元组。如果要检查集合中是否存在某些内容,它非常快(O(1)
),数组可以慢得多(O(n)
)。当然,如果你只有很少的项目,这并不重要,但是如果顺序并不重要,使用集合是一个很好的做法。如果您想要数组,您可以用[String]
交换集
let purchaseList : [(purchaseId: Int, purchaseCategory: Set<String>)] = [
(1, ["meatballs", "burger", "cheese", "onions", "apples"]),
(2, ["apple" ,"orange", "olive", "cheese"]),
(3, ["apple" ,"orange", "olive", "cheese", "Pepsi"])
]
let filtered = purchaseList.filter{ details in
details.purchaseCategory.contains("olive")
}
当然,您也可以使用struct,它基本上是一个具有超能力的元组,以更灵活和更具未来性
编辑:如果必须检查多个类别,则此选项有效:
enum Category {
case Meatballs, Burger
case Cheese, Onions, Pepsi
case Apples, Orange, Olives
}
typealias PurchaseDetails = (purchaseId: Int, purchaseCategory: Set<Category>)
let purchaseList : [PurchaseDetails] = [
(1, [.Meatballs, .Burger, .Cheese, .Onions, .Apples]),
(2, [.Apples, .Orange, .Olives, .Cheese]),
(3, [.Apples, .Orange, .Olives, .Cheese, .Pepsi])
]
func filter(includeCategories categories : Set<Category>) -> [PurchaseDetails] {
return purchaseList.filter{ details in
!details.purchaseCategory.intersect(categories).isEmpty
}
}
filter(includeCategories: [.Pepsi, .Burger])
枚举类别{
盒装肉丸、汉堡
奶酪,洋葱,百事可乐
苹果、橘子、橄榄
}
typealias PurchaseDetails=(purchaseId:Int,purchaseCategory:Set)
让purchaseList:[PurchaseDetails]=[
(1,[肉丸、汉堡、奶酪、洋葱、苹果],
(2、[苹果、橘子、橄榄、奶酪],
(3、[苹果、橘子、橄榄、奶酪、百事可乐])
]
func过滤器(包括类别:集合)->[采购详情]{
返回purchaseList.filter{中的详细信息
!details.purchaseCategory.intersect(categories).isEmpty
}
}
过滤器(包括类别:[百事可乐,.汉堡])
谢谢大家的回答。所有的答案都很有帮助。然而,我也有一个标准来检查多个类别。我找不到Swift过滤器的等效项,因此使用了NSPredicates。如果有任何与Swift过滤器相当的产品,请予以感谢
let purchaseList: [[String:AnyObject]] = [
["purchaseId":1 ,"purchaseCategory" : ["meatballs" ,"burger","cheese" ,"onions" , "apple"]],
["purchaseId":2 ,"purchaseCategory" : ["apple","orange" , "olive" , "cheese"]],
["purchaseId":3,"purchaseCategory" : ["apple","orange" , "olive" , "cheese" , "Pepsi"]]
]
var predicates = [NSPredicate]()
let categoryArray = ["olive", "Pepsi"]
for key in categoryArray {
var predicate = NSPredicate(format: "purchaseCategory contains %@", key as! String)
predicates.append(predicate)
}
var compundPredicate = NSCompoundPredicate.orPredicateWithSubpredicates(predicates)
var filteredpurchaseList = (purchaseList as NSArray?)?.filteredArrayUsingPredicate(compundPredicate) as! [[String:AnyObject]]
Answer
["purchaseId":2 ,"purchaseCategory" : ["apple","orange" , "olive" , "cheese"]],
["purchaseId":3,"purchaseCategory" : ["apple","orange" , "olive" , "cheese" , "Pepsi"]]
]
这实际上是不安全的,我知道,但我们可以假设任何purchaseId
也有purchaseCategory
array,这实际上取决于您所说的“安全”是什么意思。是的,如果字典中没有“purchaseCategory”
,或者无法转换为[String]
,则此版本将导致崩溃。但这不一定是坏事。仅返回false
会自动失败,并隐藏代码中可能存在的错误。请看原始问题的第一句话,它说,它是安全的…;-)这会将所有String
s转换为NSString
s,您可以将AnyObject
更改为Any
,以避免出现这种情况。您对我的答案有何看法您对我的答案有何看法您对我的答案有何看法您问我对您答案的看法:这很可怕,不安全,非快速和超低效。显然,你忽略了我在回答中所说的一切(除了打字错误)。我在代码中添加了适用于多个类别的代码。我认为这不是一个好的选择。NSPredicate
可以做的任何事情都可以通过filter
完成,因为filter
可以关闭。当然,在某些地方使用NSPredicate
是有意义的。这不是其中之一。这真的是太复杂了。铸造也是一个真正的问题。它很慢,而且不安全。您最好坚持使用正常的Swift方法和函数。我不明白你为什么说“我找不到Swift过滤器的等价物”-你这里有几个答案,其中几个完全符合你的要求。