почему бы вам не присвоить значение прямо вот так:var duplicateArray = originalArray
Дхармеш Хени
1
В моем случае это не работает. Это создает другой объект, который является просто ссылкой на тот же массив, и в итоге вы получаете две переменные, ссылающиеся на один и тот же массив.
user1060500 02
Ответы:
177
В Swift массивы имеют полноценную семантику, так что ничего особенного не требуется.
var duplicateArray = originalArray это все, что тебе нужно.
Если содержимое вашего массива является ссылочным типом, тогда да, это будет копировать только указатели на ваши объекты. Чтобы выполнить полное копирование содержимого, вместо этого вы должны использовать mapи выполнять копию каждого экземпляра. Для классов Foundation, которые соответствуют NSCopyingпротоколу, вы можете использовать copy()метод:
let x =[NSMutableArray(),NSMutableArray(),NSMutableArray()]let y = x
let z = x.map { $0.copy()}
x[0]=== y[0]// true
x[0]=== z[0]//false
Обратите внимание, что здесь есть подводные камни, от которых семантика значений Swift работает, чтобы защитить вас - например, поскольку NSArrayпредставляет собой неизменяемый массив, егоcopy метод просто возвращает ссылку на себя, поэтому приведенный выше тест даст неожиданные результаты.
Я пробовал это на игровой площадке с помощью этого простого кода var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }и получил такой вывод: 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 не похоже, что он копируется, знаете почему?
Фил Нидертшайдер
@PNGamingPower: x содержит адреса. y содержит копии этих адресов. Если вы измените x [0], y [0] не изменится. (попробуйте x [0] = x [1], y [0] не изменится). Таким образом, y является глубокой копией x, но вы скопировали только указатели, а не то, на что они указывают.
ragnarius 09
@ragnarius, поэтому в основном мы должны определить, что означает «копировать», копирование указателя или значения. Следовательно, это решение для копирования / дублирования массива указателей, но как вы дублируете массив значений? Гол будет, x[0] == x[1]но x[0] === y[0]не удастся
Фил Нидертшайдер
Это должен быть принятый ответ, поскольку семантика значений массива делает ненужной «копию» массива.
Скотт Ахтен
У меня это не работает. Если я буду следовать этому методу, я получу две ссылки, которые в конечном итоге указывают на один и тот же массив объектов. Если я удаляю элемент из списка, он отражается в обеих ссылках на объекты, поскольку список не был скопирован, а был просто указан объект.
user1060500 02
29
Нейт прав. Если вы работаете с примитивными массивами, все, что вам нужно сделать, это назначить duplicateArray исходному массиву.
Для полноты картины, если вы работаете с объектом NSArray, вы должны сделать следующее, чтобы сделать полную копию NSArray:
var originalArray =[1,2,3,4]asNSArrayvar duplicateArray =NSArray(array:originalArray, copyItems:true)
let z = x.map { $0}// different array with same objects
* ИЗМЕНИТЬ * редактирование начинается здесь
Выше, по сути, то же самое, что и ниже, и на самом деле использование оператора равенства ниже будет работать лучше, поскольку массив не будет скопирован, если он не будет изменен (это сделано намеренно).
добавление или удаление этого массива не повлияет на исходный массив. Однако изменение любых свойств объектов, содержащихся в массиве, будет видно в исходном массиве. Поскольку объекты в массиве не являются копиями (при условии, что массив содержит объекты, а не примитивные числа).
это действительно эффект, я это тестировал. есть два массива, если u изменится на 1, будет
Filthy Knight
1
Нет, это не так, если только массив не содержит примитивные типы вместо объектов. Тогда это действительно повлияет, как указано в ответе. Простой тестовый пример:var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
Если ваш класс поддерживает NSCopying, то продублируйте массив:let z = x.map { $0.copy as! ClassX }
Джон Панг
Если вы используете Swift BufferPointers, эту версию следует использовать в качестве прямой копии. Перед изменением значения в исходном или скопированном массиве Swift скопирует значения оригинала в копию, а затем продолжит работу. Если вместо этого вы используете указатели, Swift не будет работать, если или когда произойдут изменения, поэтому вы потенциально можете изменить оба массива.
Джастин
16
Для обычных объектов можно реализовать протокол, поддерживающий копирование, и сделать так, чтобы класс объекта реализовал этот протокол следующим образом:
Для подклассов протокол не может гарантировать, что требование init реализовано с типом подкласса. Вы объявляете протокол копирования, который реализует для вас копирование, но вы все еще реализуете clone (), что не имеет смысла.
Binarian
1
@iGodric copy предназначен для элементов в коллекции, а clone - для всей коллекции, доступной, когда копия реализована для ее элементов. Есть смысл? Кроме того, компилятор гарантирует, что подклассы действительно следуют протоколу, требуемому их родительским элементом.
johnbakers
@johnbakers О да, теперь я это вижу. Спасибо за объяснение.
Binarian
Очень чистая реализация и избегает ненужной суеты передачи каких-либо параметров в object'sфункцию init
Sylvan D Ash
0
Если вы хотите скопировать элементы массива некоторого объекта класса. Затем вы можете следовать приведенному ниже коду без использования протокола NSCopying, но вам нужен метод инициализации, который должен принимать все параметры, необходимые для вашего объекта. Вот код примера для тестирования на детской площадке.
class ABC {var a =0func myCopy()-> ABC {return ABC(value:self.a)}init(value:Int){self.a = value
}}var arrayA:[ABC]=[ABC(value:1)]var arrayB:[ABC]= arrayA.map { $0.myCopy()}
arrayB.first?.a =2
print(arrayA.first?.a)//Prints 1
print(arrayB.first?.a)//Prints2
var duplicateArray = originalArray
Ответы:
В Swift массивы имеют полноценную семантику, так что ничего особенного не требуется.
var duplicateArray = originalArray
это все, что тебе нужно.Если содержимое вашего массива является ссылочным типом, тогда да, это будет копировать только указатели на ваши объекты. Чтобы выполнить полное копирование содержимого, вместо этого вы должны использовать
map
и выполнять копию каждого экземпляра. Для классов Foundation, которые соответствуютNSCopying
протоколу, вы можете использоватьcopy()
метод:Обратите внимание, что здесь есть подводные камни, от которых семантика значений Swift работает, чтобы защитить вас - например, поскольку
NSArray
представляет собой неизменяемый массив, егоcopy
метод просто возвращает ссылку на себя, поэтому приведенный выше тест даст неожиданные результаты.источник
var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }
и получил такой вывод:0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770
не похоже, что он копируется, знаете почему?x[0] == x[1]
ноx[0] === y[0]
не удастсяНейт прав. Если вы работаете с примитивными массивами, все, что вам нужно сделать, это назначить duplicateArray исходному массиву.
Для полноты картины, если вы работаете с объектом NSArray, вы должны сделать следующее, чтобы сделать полную копию NSArray:
источник
Есть третий вариант ответа Нейта:
* ИЗМЕНИТЬ * редактирование начинается здесь
Выше, по сути, то же самое, что и ниже, и на самом деле использование оператора равенства ниже будет работать лучше, поскольку массив не будет скопирован, если он не будет изменен (это сделано намеренно).
Подробнее см. Здесь: https://developer.apple.com/swift/blog/?id=10.
* ИЗМЕНИТЬ * редактирование заканчивается здесь
добавление или удаление этого массива не повлияет на исходный массив. Однако изменение любых свойств объектов, содержащихся в массиве, будет видно в исходном массиве. Поскольку объекты в массиве не являются копиями (при условии, что массив содержит объекты, а не примитивные числа).
источник
var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
NSCopying
, то продублируйте массив:let z = x.map { $0.copy as! ClassX }
Для обычных объектов можно реализовать протокол, поддерживающий копирование, и сделать так, чтобы класс объекта реализовал этот протокол следующим образом:
А затем расширение Array для клонирования:
и это почти все, чтобы просмотреть код и образец, проверьте эту суть
источник
object's
функцию initЕсли вы хотите скопировать элементы массива некоторого объекта класса. Затем вы можете следовать приведенному ниже коду без использования протокола NSCopying, но вам нужен метод инициализации, который должен принимать все параметры, необходимые для вашего объекта. Вот код примера для тестирования на детской площадке.
источник