如何检查 object 数组中 object 属性的相等性。 Swift
How to check equality of object properties in an array of objects. Swift
我有一个名为 Movie 的 class,截至目前,它只有一个名为 movieTitle 的字符串 属性。
我有一个 Movie 数组,使用 .contains 方法 returns false 即使数组中有一个 object 具有相同的标题。有趣的是,.contains 在我制作的游乐场中有效,但在应用程序设置中无效。
感谢您的帮助!我是编程游戏的新手,所以如果你和 ELI5 东西,那就太好了!
这是我的代码片段。最终会发生什么,它只是不断将相同的 10 个条目添加到数组中。
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String: AnyObject]
if let movieSearch = json["Search"] as? [[String: AnyObject]] {
for movie in movieSearch {
if let title = movie["Title"] as? String {
let newMovie = Movie(movieTitle: title)!
if (!self.movieList.contains(newMovie)) {
self.movieList.append(newMovie)
}
self.tableView.reloadData()
}
}
}
}catch {
print("Error with Json: \(error)")
}
电影Class
import UIKit
class Movie: NSObject, NSCoding {
// MARK: Properties
struct PropertyKey {
static let movieTitleKey = "title"
}
// MARK: Archiving Paths
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("Movies")
var movieTitle: String
// MARK: Initialization
init?(movieTitle: String) {
// Initialize stored properties.
self.movieTitle = movieTitle
super.init()
// Initialization should fail if there is no itemName
if movieTitle.isEmpty {
return nil
}
}
// MARK: NSCoding
func encode(with aCoder: NSCoder) {
aCoder.encode(movieTitle, forKey: PropertyKey.movieTitleKey)
}
required convenience init?(coder aDecoder: NSCoder) {
let title = aDecoder.decodeObject(forKey: PropertyKey.movieTitleKey) as! String
//Must call designated initializer.
self.init(movieTitle: title)
}
}
// MARK: Equatable
func ==(lhs: Movie, rhs: Movie) -> Bool { // Implement Equatable
return lhs.movieTitle == rhs.movieTitle
}
在操场上有什么用
class Movie: NSObject {
var movieTitle: String
init?(movieTitle: String) {
// Initialize stored properties.
self.movieTitle = movieTitle
super.init()
// Initialization should fail if there is no itemName
if movieTitle.isEmpty {
return nil
}
}
}
var movieList = [Movie]()
var movie1 = Movie(movieTitle: "Batman")
var movie2 = Movie(movieTitle: "Batman")
var movie3 = Movie(movieTitle: "Superman")
movieList.append(movie1!)
movieList.append(movie2!)
movieList.contains(movie1!) // Returns True
movieList.contains(movie3!) // Returns False
因为你的Movie
class(为什么是class?)继承自NSObject
(为什么?),它继承了NSObject
的Equatable
协议的一致性,以及 ==
的 NSObject
实现。默认情况下,这会进行身份比较(比较引用),而不是值比较。
这是一个例子:
let movie1 = Movie(movieTitle: "Batman")
let movie2 = Movie(movieTitle: "Batman")
var movieList = [Movie1]
movieList.contains(movie1!) // True, because movie1 was added in
movieList.contains(movie2!) // False, movie2 was never added
由于 Movie
不会使用比较其值的实现(例如 movieTitle
)覆盖 ==
,因此它遵循默认实现,即比较参考资料。尽管 movie2
具有相同的 value
,但它是一个具有自己(单独的)内存位置的不同对象。因此,身份比较失败,没有找到。
要解决此问题,如果 Movie
的所有字段都匹配,则将 ==
设置为 return true。但是,您尝试做的事情可能比 implemented with structs 更好。
你应该试试这个方法。
var filtered = [Movie]()
filtered = movieList.filter({[=10=].movieTitle == "Superman"})
if filtered.count == 1 {
//so,"Superman" movie contained in array..
}
让我知道结果...谢谢。
尝试覆盖 NSObject
的 isEqual
方法,因为它已经符合 Equatable
协议。您可以在操场上测试下面的代码。希望对你有帮助。
class Movie: NSObject {
var movieTitle: String
init?(movieTitle: String) {
// Initialize stored properties.
self.movieTitle = movieTitle
super.init()
// Initialization should fail if there is no itemName
if movieTitle.isEmpty {
return nil
}
}
override func isEqual(_ object: Any?) -> Bool {
guard let theMovie = (object as? Movie) else { return false }
return movieTitle == theMovie.movieTitle
}
}
var movieList = [Movie]()
func appendToList(newMovie: Movie) {
if (!movieList.contains(newMovie)) {
movieList.append(newMovie)
}
}
var movie1 = Movie(movieTitle: "Batman")
var movie2 = Movie(movieTitle: "Batman")
var movie3 = Movie(movieTitle: "Superman")
appendToList(newMovie: movie1!)
movieList.count // count is 1
appendToList(newMovie: movie2!)
movieList.count // count is still 1 not incremented
movieList.contains(movie1!) // Returns true
movieList.contains(movie2!) // Returns true
movieList.contains(movie3!) // Returns false
只需尝试使用此代码即可完美运行。
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String: AnyObject]
if let movieSearch = json["Search"] as? [[String: AnyObject]] {
for movie in movieSearch {
if let title = movie["Title"] as? String {
let newMovie = Movie(movieTitle: title)!
let movieTitles = (self.movieList as NSArray).value(forKeyPath: "movieTitle") as? [String]
if movieTitles == nil || movieTitles!.contains(title) == false {
self.movieList.append(newMovie)
}
self.tableView.reloadData()
}
}
}
}catch {
print("Error with Json: \(error)")
}
我有一个名为 Movie 的 class,截至目前,它只有一个名为 movieTitle 的字符串 属性。
我有一个 Movie 数组,使用 .contains 方法 returns false 即使数组中有一个 object 具有相同的标题。有趣的是,.contains 在我制作的游乐场中有效,但在应用程序设置中无效。
感谢您的帮助!我是编程游戏的新手,所以如果你和 ELI5 东西,那就太好了!
这是我的代码片段。最终会发生什么,它只是不断将相同的 10 个条目添加到数组中。
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String: AnyObject]
if let movieSearch = json["Search"] as? [[String: AnyObject]] {
for movie in movieSearch {
if let title = movie["Title"] as? String {
let newMovie = Movie(movieTitle: title)!
if (!self.movieList.contains(newMovie)) {
self.movieList.append(newMovie)
}
self.tableView.reloadData()
}
}
}
}catch {
print("Error with Json: \(error)")
}
电影Class
import UIKit
class Movie: NSObject, NSCoding {
// MARK: Properties
struct PropertyKey {
static let movieTitleKey = "title"
}
// MARK: Archiving Paths
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("Movies")
var movieTitle: String
// MARK: Initialization
init?(movieTitle: String) {
// Initialize stored properties.
self.movieTitle = movieTitle
super.init()
// Initialization should fail if there is no itemName
if movieTitle.isEmpty {
return nil
}
}
// MARK: NSCoding
func encode(with aCoder: NSCoder) {
aCoder.encode(movieTitle, forKey: PropertyKey.movieTitleKey)
}
required convenience init?(coder aDecoder: NSCoder) {
let title = aDecoder.decodeObject(forKey: PropertyKey.movieTitleKey) as! String
//Must call designated initializer.
self.init(movieTitle: title)
}
}
// MARK: Equatable
func ==(lhs: Movie, rhs: Movie) -> Bool { // Implement Equatable
return lhs.movieTitle == rhs.movieTitle
}
在操场上有什么用
class Movie: NSObject {
var movieTitle: String
init?(movieTitle: String) {
// Initialize stored properties.
self.movieTitle = movieTitle
super.init()
// Initialization should fail if there is no itemName
if movieTitle.isEmpty {
return nil
}
}
}
var movieList = [Movie]()
var movie1 = Movie(movieTitle: "Batman")
var movie2 = Movie(movieTitle: "Batman")
var movie3 = Movie(movieTitle: "Superman")
movieList.append(movie1!)
movieList.append(movie2!)
movieList.contains(movie1!) // Returns True
movieList.contains(movie3!) // Returns False
因为你的Movie
class(为什么是class?)继承自NSObject
(为什么?),它继承了NSObject
的Equatable
协议的一致性,以及 ==
的 NSObject
实现。默认情况下,这会进行身份比较(比较引用),而不是值比较。
这是一个例子:
let movie1 = Movie(movieTitle: "Batman")
let movie2 = Movie(movieTitle: "Batman")
var movieList = [Movie1]
movieList.contains(movie1!) // True, because movie1 was added in
movieList.contains(movie2!) // False, movie2 was never added
由于 Movie
不会使用比较其值的实现(例如 movieTitle
)覆盖 ==
,因此它遵循默认实现,即比较参考资料。尽管 movie2
具有相同的 value
,但它是一个具有自己(单独的)内存位置的不同对象。因此,身份比较失败,没有找到。
要解决此问题,如果 Movie
的所有字段都匹配,则将 ==
设置为 return true。但是,您尝试做的事情可能比 implemented with structs 更好。
你应该试试这个方法。
var filtered = [Movie]()
filtered = movieList.filter({[=10=].movieTitle == "Superman"})
if filtered.count == 1 {
//so,"Superman" movie contained in array..
}
让我知道结果...谢谢。
尝试覆盖 NSObject
的 isEqual
方法,因为它已经符合 Equatable
协议。您可以在操场上测试下面的代码。希望对你有帮助。
class Movie: NSObject {
var movieTitle: String
init?(movieTitle: String) {
// Initialize stored properties.
self.movieTitle = movieTitle
super.init()
// Initialization should fail if there is no itemName
if movieTitle.isEmpty {
return nil
}
}
override func isEqual(_ object: Any?) -> Bool {
guard let theMovie = (object as? Movie) else { return false }
return movieTitle == theMovie.movieTitle
}
}
var movieList = [Movie]()
func appendToList(newMovie: Movie) {
if (!movieList.contains(newMovie)) {
movieList.append(newMovie)
}
}
var movie1 = Movie(movieTitle: "Batman")
var movie2 = Movie(movieTitle: "Batman")
var movie3 = Movie(movieTitle: "Superman")
appendToList(newMovie: movie1!)
movieList.count // count is 1
appendToList(newMovie: movie2!)
movieList.count // count is still 1 not incremented
movieList.contains(movie1!) // Returns true
movieList.contains(movie2!) // Returns true
movieList.contains(movie3!) // Returns false
只需尝试使用此代码即可完美运行。
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String: AnyObject]
if let movieSearch = json["Search"] as? [[String: AnyObject]] {
for movie in movieSearch {
if let title = movie["Title"] as? String {
let newMovie = Movie(movieTitle: title)!
let movieTitles = (self.movieList as NSArray).value(forKeyPath: "movieTitle") as? [String]
if movieTitles == nil || movieTitles!.contains(title) == false {
self.movieList.append(newMovie)
}
self.tableView.reloadData()
}
}
}
}catch {
print("Error with Json: \(error)")
}