用另一个数组过滤(可编码)数组 [英] Filter an (Codable) array by another array
问题描述
我正在尝试通过ID过滤json数据(尝试标记一些收藏夹并使用它进行过滤)
I'm trying to filter my json data by IDs (trying mark some favourites and filter using it)
struct workoutList : Codable {
let id : Int
let title : String
let tag : String
}
func selectedWorkoutGroup(libraryFilter: Int, jsonErgWorkouts:[workoutList], workoutGroupBox: UITextField) -> [workoutList] {
var selectedGroup = [workoutList]()
let workoutFav = [1,10,100]
if libraryFilter == 0 {
// This works because I'm filtering based on 1 specific item
selectedGroup = jsonErgWorkouts.filter { $0.tag == workoutGroupBox.text }
} else if libraryFilter == 1 {
// Here I want to filter and show only the favorites
selectedGroup = jsonErgWorkouts.filter { $0.id } //
print("selectedGroup:\(selectedGroup)")
}
return selectedGroup
}
在上面的代码中,当我有1(一个)特定项目要过滤,然后获得带有该标签的整个json数组时,过滤器便起作用.
in the above code, the filter works when I have 1(one) something specific item to filter and then I get the entire json array with that tag.
现在,我要实现一个收藏夹列表,用户在其中选择ID == [1,10,100]作为他们的收藏夹.
Now I want to implement a favorite list, where the user selects for example ID == [1, 10 ,100] as their favourite.
如何使用filter命令执行此操作?我尝试了几件事,然后搜索了SO(但不起作用).大多数答案都是基于对特定项目的过滤,例如:
How can I use the filter command to do it? I tried a few things and searched through SO (but doesn't work). Most of the answers are based on filtering based on specific items eg:
selectedGroup = jsonErgWorkouts.filter { workoutFav?.contains($0.id) }
edit :(省略了我正在使用/存储userDefaults中的收藏夹的代码.此代码给出了表达式类型在没有更多上下文的情况下模棱两可"的错误
edit: (omitted that I am using/storing the favourites in userDefaults. This code gives the error of "type of expression is ambiguous without more context"
func selectedWorkoutGroup(libraryFilter: Int, jsonErgWorkouts:[workoutList], workoutGroupBox: UITextField) -> [workoutList] {
var selectedGroup = [workoutList]()
UserDefaults.standard.set([1,10,100], forKey: "workoutFavorite")
/// This one gets stored as [Any] so I cast it to [Int]
let workoutFav = UserDefaults.standard.array(forKey: "workoutFavorite") as? [Int]
if libraryFilter == 0 {
// This works because I'm filtering based on 1 specific item
selectedGroup = jsonErgWorkouts.filter { $0.tag == workoutGroupBox.text }
} else if libraryFilter == 1 {
selectedGroup = workoutFav.flatMap { favouriteId in // for each favourite ID
jsonErgWorkouts.filter { $0.id == favouriteId } // This returns Error "type of expression is ambiguous without more context"
} // flatMap joins all those arrays returns by "filter" together, no need to do anything else
print("selectedGroup:\(selectedGroup)")
}
return selectedGroup
}
最终解决方案:从此更改
Final Solution: Changing from This
let workoutFav = UserDefaults.standard.array(forKey: "workoutFavorite") as? [Int]
到此(注意as!而不是as?)
to This (notice the as! instead of as?)
let workoutFav = UserDefaults.standard.array(forKey: "workoutFavorite") as! [Int]
使用@sweeper的答案工作.谢谢
works using @sweeper's answer. Thanks
更新:弄清楚为什么会发生此错误,表达式类型在没有更多上下文的情况下是模棱两可的".在将UserDefaults 的输出转换为as时?[Int]
,不得不使用 as![Int]
Update:
Figured out why this error occurred "type of expression is ambiguous without more context" when casting the output of UserDefaults as? [Int]
and had to use as! [Int]
但是使用 as![Int]
强制展开,如果用户没有将任何收藏夹保存到UserDefault中,则会导致应用程序崩溃.(然后我不得不编写代码)如下
But using as! [Int]
force unwrapping it causes app to crash if the user did not have any favorites saved into the UserDefault. (Which I then had to code around) like below
var workoutFav = [Int]()
if !(UserDefaults.standard.array(forKey: "workoutFavorite") == nil) {
workoutFav = UserDefaults.standard.array(forKey: "workoutFavorite") as! [Int]
}
然后根据此SO简化并取消了展开力的操作 https://stackoverflow.com/a/37357869/14414215 成为这一行
Which was then simplified and removed the force unwrapping based on this SO https://stackoverflow.com/a/37357869/14414215 to become this one-line
let workoutFav = UserDefaults.standard.array(forKey: "workoutFavorite") as? [Int] ?? [Int]()
推荐答案
您需要对收藏夹数组中的每个ID进行过滤.结果得到一个数组数组.要获得最终阵列,您需要将这些阵列连接到单个阵列.这将每件事映射到阵列并加入阵列".操作是 flatMap
所做的:
You need to do that filter for each id in the favourites array. You get an array of arrays as a result. To get the final array, you need to join those arrays to a single array. This "map each thing to an array and join the arrays" operation is what a flatMap
does:
workoutFav.flatMap { favouriteId in // for each favourite ID
jsonErgWorkouts.filter { $0.id == favouriteId } // find workouts that match the ID
} // flatMap joins all those arrays returns by "filter" together, no need to do anything else
这篇关于用另一个数组过滤(可编码)数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!