У меня есть следующий вложенный массив, и я пытаюсь подсчитать, сколько там элементов с уникальным ids
. В массиве ниже счетчик должен быть 2.
Массив имеет тип List<SolData>
, он поступает из Realm
class SolData: Object {
@objc dynamic var uid = "";
@objc dynamic var id = "";
}
extension SolData: ListDiffable {
func diffIdentifier() -> NSObjectProtocol {
return uid as NSObjectProtocol
}
func isEqual(toDiffableObject object: ListDiffable?) -> Bool {
if let object = object as? SolData {
return uid == object.uid
}
return false
}
}
Печать массива.
(
[0] SolData {
uid = sdasd;
id = jmX3;
},
[1] SolData {
uid = gfd;
id = jmX3;
},
[2] SolData {
uid = hgfd;
id = jmX3;
},
[3] SolData {
uid = terw;
id = jmX3;
},
[4] SolData {
uid = fgg;
id = GFdda;
}
)
Я пробовал использовать map
следующим образом
var count = 0;
var prevId = "";
let uniqueSols = diff.sol.map{ (s) -> Int in
if s.id != prevId {
count = count + 1;
prevId = s.id;
}
return count;
}
print(uniqueSols);
Но я получаю следующую ошибку.
SWIFT RUNTIME BUG: unable to demangle type of field '_transform'. mangled type name is 'q_7ElementSTQzc' 2018-10-27 14:26:08.793528+0300 App[23634:611928] SWIFT RUNTIME BUG: unable to demangle type of field '_transform'. mangled type name is 'q_7ElementSTQzc', _transform: ())
Добавлен еще код. Нет поля _transform. Мне это кажется странной ошибкой.
Что такое ListDiffable
и Object
?
Вы хотите знать уникальные элементы или просто их количество? map
предназначен для превращения входных элементов n
в выходные элементы n
. Чтобы превратить входные элементы n
в выходной элемент 1
(счет будет только одним выходом), вы должны вместо этого использовать reduce
.
Почему голосование против? Я все время возвращаюсь к этому вопросу.
Чтобы воспроизвести ваш код, я собираюсь имитировать класс SolData
и добавить инициализатор, чтобы упростить создание экземпляра:
class SolData {
var uid: String = ""
var id: String = ""
init(uid: String, id: String) {
self.uid = uid
self.id = id
}
}
Создадим несколько экземпляров:
let zero = SolData(uid: "sdasd", id: "jmX3")
let one = SolData(uid: "gfd", id: "jmX3")
let two = SolData(uid: "hgfd", id: "jmX3")
let three = SolData(uid: "terw", id: "jmX3")
let four = SolData(uid: "fgg", id: "GFdda")
И сгруппируйте их в массив:
let array = [zero, one, two, three, four]
Чтобы получить только экземпляры с уникальными идентификаторами, воспользуемся reduce(into:)
:
let uniqueIds = array.reduce(into: Set<String>(), { $0.insert($1.id)})
Свойство count uniqueIds
- это количество уникальных идентификаторов в array
:
let uniqueIdsCount = uniqueIds.count //2
Если вам нужен массив экземпляров с уникальными идентификаторами, используйте следующее:
let instancesWithUniqueIds = array.reduce(into: [SolData]()) { accumulator, element in
if accumulator.allSatisfy({ $0.id != element.id}) {
accumulator.append(element)
}
}
accumulator.allSatisfy({ $0.id != element.id})
можно заменить на accumulator.contains(element)
и сделать SolData
совместимым с Hashable
.
Чувак! Спасибо, это именно то, что мне было нужно!
Привет, @ Carpsen90, я все время возвращаюсь к этому, но у меня есть еще один вопрос, связанный с вышеизложенным. У меня есть другая часть приложения, где я использую петлю for each
и решения append
для var arr: [SolData] = [SolData]();
. Когда я пытаюсь уменьшить этот массив, появляется следующая ошибка: Cannot assign value of type 'Set<AnyHashable>' to type '[SolData]'
. Почему в этом случае вышеуказанное не сокращает работу?
@Ando Это было бы более подходящим для нового вопроса, но я добавил код, чтобы дать вам массив уникальных экземпляров, вместо того, что запрашивал исходный вопрос: количество уникальных идентификаторов.
Огромное спасибо! Я думаю, что это хорошее дополнение к ответу, потому что они обычно используются; кроме того, сейчас я могу подсчитать сокращение результатов второй части вашего ответа. Еще раз спасибо за это!
С какого массива вы начинаете? а что такое
jmX3
иGFdda
? А что такое поле_transform
? Сделайте так, чтобы ваш вопрос было легко воспроизвести на детской площадке