Найти элемент и изменить значение в настраиваемом массиве объектов - Swift
У меня этот класс
class InboxInterests {
var title = ""
var eventID = 0
var count = ""
var added = 0
init(title : String, eventID : NSInteger, count: String, added : NSInteger) {
self.title = title
self.eventID = eventID
self.count = count
self.added = added
}
}
И я использую его как это
var array: [InboxInterests] = [InboxInterests]()
Добавить элемент
let post = InboxInterests(title: "test",eventID : 1, count: "test", added: 0)
self.array.append(post)
Я хочу найти индекс клавишей eventID
и изменить значение added
в том же индексе
Как это возможно?
Ответы
Ответ 1
Используйте фильтр и сначала найдите значение:
array.filter({$0.eventID == id}).first?.added = value
В этом вы:
- фильтровать массив до элементов, соответствующих идентификатору события
- выберите первый результат, если есть
- затем установите значение
РЕДАКТИРОВАТЬ: В Swift 3 вы можете сохранить себе пару символов
array.first({$0.eventID == id})?.added = value
РЕДАКТИРОВАТЬ: Swift 4.2:
array.first(where: { $0.eventID == id })?.added = value
array.filter {$0.eventID == id}.first?.added = value
Ответ 2
Для меня вышеуказанный ответ не сработал. Итак, сначала я нашел индекс объекта, который я хочу заменить, а затем с помощью индекса заменил его новым значением.
if let row = self.upcoming.index(where: {$0.eventID == id}) {
array[row] = newValue
}
В Swift 5.0:
if let row = self.upcoming.firstIndex(where: {$0.eventID == id}) {
array[row] = newValue
}
Ответ 3
В этом случае оператор фильтра не самый лучший, он работает для некоторых из вас, потому что классы передаются по ссылке.
Объяснение: (Вы можете скопировать следующий код на игровой площадке, если вы хотите его проверить).
class Book {
let id: Int
var title = "default"
init (id: Int) {
self.id = id
}
}
var arrayBook = [Book]()
arrayBook.append(Book(id: 0))
arrayBook.append(Book(id:1))
arrayBook.forEach { book in
print(book.title)
}
arrayBook.filter{ $0.id == 1 }.first?.title = "modified"
arrayBook.forEach { book in
print(book.title)
}
Массивы копируются по значению not reference, поэтому, когда вы используете фильтр, вы создаете новый массив (отличный от исходного), но когда вы изменяете новый, исходный изменяется также, потому что оба указывают на тот же класс (classed передаются по ссылке), поэтому после фильтра ваш массив будет изменен, а новый будет освобожден. Таким образом, в этом случае он будет печатать " по умолчанию", "по умолчанию" , а затем "по умолчанию," изменено ".
Что произойдет, если вы измените class
на struct
, значение будет передано значением not reference, так что у вас будет 2 массива в памяти с разными значениями, поэтому, если вы перейдете через arrayBooks
снова, он будет распечатываться раньше фильтр "по умолчанию" , "по умолчанию" , а затем "по умолчанию" , "по умолчанию" . Потому что, когда вы используете фильтр, который вы создаете и изменяете новый массив, который будет освобожден, если вы его не сохраните).
Решение использует карту, создавая новый массив со всеми значениями, но с измененными элементами или полями, которые мы хотим, а затем заменим наш массив новым. Это приведет к печати "по умолчанию" , "по умолчанию" до карты, а затем "по умолчанию" , "изменено"
Это будет работать с структурами, классами и всем, что вы хотите:).
struct Book {
let id: Int
var title = "default"
init (id: Int) {
self.id = id
}
}
var arrayBook = [Book]()
arrayBook.append(Book(id: 0))
arrayBook.append(Book(id:1))
arrayBook.forEach { book in
print(book.title)
}
arrayBook = arrayBook.map{
var mutableBook = $0
if $0.id == 1 {
mutableBook.title = "modified"
}
return mutableBook
}
arrayBook.forEach { book in
print(book.title)
}