Подсчет уникальных идентификаторов во вложенном массиве с использованием Swift

У меня есть следующий вложенный массив, и я пытаюсь подсчитать, сколько там элементов с уникальным 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: ())

С какого массива вы начинаете? а что такое jmX3 и GFdda? А что такое поле _transform? Сделайте так, чтобы ваш вопрос было легко воспроизвести на детской площадке

ielyamani 27.10.2018 13:38

Добавлен еще код. Нет поля _transform. Мне это кажется странной ошибкой.

Ando 27.10.2018 13:46

Что такое ListDiffable и Object?

ielyamani 27.10.2018 13:50

Вы хотите знать уникальные элементы или просто их количество? map предназначен для превращения входных элементов n в выходные элементы n. Чтобы превратить входные элементы n в выходной элемент 1 (счет будет только одним выходом), вы должны вместо этого использовать reduce.

Mecki 27.10.2018 13:55

Почему голосование против? Я все время возвращаюсь к этому вопросу.

Ando 09.11.2018 12:50
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
5
184
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы воспроизвести ваш код, я собираюсь имитировать класс 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.

Чувак! Спасибо, это именно то, что мне было нужно!

Ando 27.10.2018 14:04

Привет, @ Carpsen90, я все время возвращаюсь к этому, но у меня есть еще один вопрос, связанный с вышеизложенным. У меня есть другая часть приложения, где я использую петлю for each и решения append для var arr: [SolData] = [SolData]();. Когда я пытаюсь уменьшить этот массив, появляется следующая ошибка: Cannot assign value of type 'Set<AnyHashable>' to type '[SolData]'. Почему в этом случае вышеуказанное не сокращает работу?

Ando 15.11.2018 11:36

@Ando Это было бы более подходящим для нового вопроса, но я добавил код, чтобы дать вам массив уникальных экземпляров, вместо того, что запрашивал исходный вопрос: количество уникальных идентификаторов.

ielyamani 15.11.2018 12:22

Огромное спасибо! Я думаю, что это хорошее дополнение к ответу, потому что они обычно используются; кроме того, сейчас я могу подсчитать сокращение результатов второй части вашего ответа. Еще раз спасибо за это!

Ando 15.11.2018 12:40

Другие вопросы по теме