Классы являются ссылочными типами, поэтому, как вы заметили, все элементы массива в
var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0))
ссылаются на один и тот же экземпляр объекта (который создается первым, а затем передается как аргумент инициализатору массива).
Для типа struct
вы получите другой результат.
Возможное решение:
var users = (0 ..< howManyUsers).map { _ in User(thinkTime: 10.0) }
Здесь создается экземпляр User
для каждого из индексов массива.
Если вам это нужно часто, вы можете определить метод инициализации массива, который принимает параметр «автозакрытия»:
extension Array {
public init(count: Int, @autoclosure elementCreator: () -> Element) {
self = (0 ..< count).map { _ in elementCreator() }
}
}
var users = Array(count: howManyUsers, elementCreator: User(thinkTime: 10.0) )
Теперь второй аргумент User(thinkTime: 10.0)
завершается компилятором в закрытие, а закрытие выполняется для каждого индекса массива.
Обновление для Swift 3:
extension Array {
public init(count: Int, elementCreator: @autoclosure () -> Element) {
self = (0 ..< count).map { _ in elementCreator() }
}
}
Сила numpy / scipy / pandas заключается в использовании кода C для выполнения большей части работы за вас. Учитывая, что, по вашим словам, есть 300 тыс. Строк и 80 столбцов, я предлагаю вам сначала приложить все усилия, чтобы убедиться, что вы обрабатываете строки в C, а не в python. Таким образом, ваш первый цикл должен быть исключен: не обрабатывайте 300k элементов, используя python.
Как я читаю ваши требования, у вас есть индекс (метки строк), в котором есть значения какого-то типа, которые могут отображаться в отдельных ячейках в других ваших столбцах. Примерно так:
Index A B C D
1 0 0 3 0
2 2 0 1 -1
3 0 0 0 0
192 0 0 1 -1
Вы хотите знать, для каждого индекса, есть ли это значение в каком-либо из столбца A, столбца B, столбца C и т. Д. Если любое значение индекса появляется в столбце, этот столбец "ALIVE".
В конце процесса столбцы либо ALIVE, либо нет, и затем вы хотите отфильтровать другой словарь, чтобы исключить столбцы, которые не являются ALIVE.
В моем примере выше столбец A считается живым из-за {2}, а столбец C считается живым из-за {3, 1}, но столбцы B и D не являются живыми, потому что они не содержат никаких значений, которые присутствуют в указателе. Это правильно?
Попробуйте использовать isin
, чтобы определить, присутствуют ли значения в столбцах в индексе. Затем используйте any
, чтобы свести логические результаты к одному логическому значению, которое определяет, является ли столбец живым:
row_labels = df.index
col_is_alive = df.isin(row_labels).any() # NB: any(index=0) is default
(ПРИМЕЧАНИЕ: я не в том месте, где я могу запустить этот код. Это может содержат синтаксис или другие ошибки.)
Теперь у вас есть серия из 80 логических значений, сообщающих, какие столбцы живы. Вы можете делать свою обработку так, как вам нравится.
alive_col_names = { name for name in df.columns if col_is_alive[name] } # Set comprehension
Тем не менее, ваше первоначальное постановка проблемы звучит так, как будто вы делаете это один раз (в отличие от итеративного обновления групп имен столбцов). В этом случае, вместо того, чтобы пересекать значения словаря (списки каждого имени столбца, кроме ключа), я бы предложил просто вычислить значения напрямую. То есть вычислять пары ключ-> значение напрямую, а не пытаться «пересекать» списки значений с этим списком всех имен столбцов.
col_dict = { key:alive_col_names - {key} for key in alive_col_names}
С другой стороны, если вы каким-то образом итеративно обновляете эти значения, я бы посоветовал вам сделать вашу вторую структуру данных словарём строки -> set вместо string -> list, так как это даст вам доступ стандартным операциям над множеством и поведению.
new_col_dict = {}
for key, other_cols in col_dict.items():
if key not in alive_col_names:
continue
new_col_dict[key] = other_cols.interset(alive_col_names)
col_dict = new_col_dict
(Которые могут быть свернуты с использованием разборчивого понимания, но, возможно, не в интересах читабельности.)