Eu quero enumerar por meio de uma matriz em Swift e remover certos itens. Estou me perguntando se isso é seguro de fazer e, se não, como devo fazer isso.
Atualmente, eu estaria fazendo isso:
for (index, aString: String) in enumerate(array) {
//Some of the strings...
array.removeAtIndex(index)
}
ios
arrays
swift
enumeration
Andrew
fonte
fonte
filter
retorna uma nova matriz. Você não está removendo nada do array. Eu nem mesmo chamariafilter
uma enumeração. Sempre há mais de uma maneira de esfolar um gato.Você pode considerar a
filter
maneira:var theStrings = ["foo", "bar", "zxy"] // Filter only strings that begins with "b" theStrings = theStrings.filter { $0.hasPrefix("b") }
O parâmetro de
filter
é apenas um encerramento que recebe uma instância do tipo array (neste casoString
) e retorna aBool
. Quando o resultado é,true
ele mantém o elemento, caso contrário, o elemento é filtrado.fonte
filter
não atualiza o array, ele apenas retorna um novofilter
método em ummutating
(como li, amutating
palavra - chave permite que funções como essa sejam alteradasself
)?Array
marcá-lo comomutating
e semelhante ao código da pergunta. De qualquer forma, considere que isso nem sempre é uma vantagem. De qualquer forma, toda vez que você remove um objeto, seu array pode ser reorganizado na memória. Assim, poderia ser mais eficiente alocar um novo array e então fazer uma substituição atômica com o resultado da função de filtro. O compilador pode fazer ainda mais otimizações, dependendo do seu código.No Swift 3 e 4 , isso seria:
Com números, de acordo com a resposta de Johnston:
var a = [1,2,3,4,5,6] for (i,num) in a.enumerated().reversed() { a.remove(at: i) } print(a)
Com strings como a pergunta do OP:
var b = ["a", "b", "c", "d", "e", "f"] for (i,str) in b.enumerated().reversed() { if str == "c" { b.remove(at: i) } } print(b)
No entanto, agora no Swift 4.2 ou posterior, existe uma maneira ainda melhor e mais rápida que foi recomendada pela Apple em WWDC2018:
var c = ["a", "b", "c", "d", "e", "f"] c.removeAll(where: {$0 == "c"}) print(c)
Esta nova forma tem várias vantagens:
filter
.fonte
{$0 === Class.self}
não funcionaQuando um elemento em um determinado índice é removido de uma matriz, todos os elementos subsequentes terão sua posição (e índice) alterados, porque eles mudam uma posição para trás.
Portanto, a melhor maneira é navegar pelo array na ordem inversa - e, neste caso, sugiro usar um loop for tradicional:
for var index = array.count - 1; index >= 0; --index { if condition { array.removeAtIndex(index) } }
No entanto, na minha opinião, a melhor abordagem é usar o
filter
método, conforme descrito por @perlfly em sua resposta.fonte
Não, não é seguro transformar arrays durante a enumaração, seu código irá travar.
Se você deseja excluir apenas alguns objetos, você pode usar a
filter
função.fonte
filter
é mais seguro . Aqui está meu exemplo idiota:var y = [1, 2, 3, 4, 5]; print(y); for (index, value) in y.enumerated() { y.remove(at: index) } print(y)
Crie uma matriz mutável para armazenar os itens a serem excluídos e, em seguida, após a enumeração, remova esses itens do original. Ou crie uma cópia do array (imutável), enumere e remova os objetos (não por índice) do original durante a enumeração.
fonte
O loop for tradicional pode ser substituído por um loop while simples, útil se você também precisar realizar algumas outras operações em cada elemento antes da remoção.
var index = array.count-1 while index >= 0 { let element = array[index] //any operations on element array.remove(at: index) index -= 1 }
fonte
Eu recomendo definir os elementos como nulo durante a enumeração e, depois de concluir, remover todos os elementos vazios usando o método arrays filter ().
fonte
filter
método não remove, ele gera um novo array.Apenas para adicionar, se você tiver vários arrays e cada elemento no índice N do array A estiver relacionado ao índice N do array B, então você ainda pode usar o método invertendo o array enumerado (como nas respostas anteriores). Mas lembre-se de que ao acessar e excluir os elementos dos outros arrays, não há necessidade de revertê-los.
Like so, (one can copy and paste this on Playground) var a = ["a", "b", "c", "d"] var b = [1, 2, 3, 4] var c = ["!", "@", "#", "$"] // remove c, 3, # for (index, ch) in a.enumerated().reversed() { print("CH: \(ch). INDEX: \(index) | b: \(b[index]) | c: \(c[index])") if ch == "c" { a.remove(at: index) b.remove(at: index) c.remove(at: index) } } print("-----") print(a) // ["a", "b", "d"] print(b) // [1, 2, 4] print(c) // ["!", "@", "$"]
fonte