用另一个数组过滤(可编码)数组 [英] Filter an (Codable) array by another array

查看:58
本文介绍了用另一个数组过滤(可编码)数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆