A melhor maneira de remover valores duplicados ( NSString
) do NSMutableArray
Objective-C?
Essa é a maneira mais fácil e correta de fazer isso?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
ios
objective-c
nsmutablearray
Teo Choong Ping
fonte
fonte
Respostas:
Sua
NSSet
abordagem é a melhor se você não está preocupado com a ordem dos objetos, mas, novamente, se você não está preocupado com a ordem, por que não está armazenando-os em umNSSet
para começar?Eu escrevi a resposta abaixo em 2009; em 2011, a Apple adicionou
NSOrderedSet
ao iOS 5 e Mac OS X 10.7. O que havia sido um algoritmo agora são duas linhas de código:Se você estiver preocupado com o pedido e estiver executando o iOS 4 ou anterior, faça um loop sobre uma cópia da matriz:
fonte
[NSOrderedSet orderedSetWithArray:array];
Você pode recuperar uma matriz viaarray = [orderedSet allObjects];
ou apenas usarNSOrderedSet
s em vez deNSArray
em primeiro lugar.[orderedSet allObjects]
com[orderedSet array]
!NSArray
e devemos criar tempNSMutableArray
. No seu exemplo você trabalha vice-versaNSSet
) ou o link @Simon Whitaker impede antes de adicionar valor duplicado, o que é uma maneira eficiente?Sei que essa é uma pergunta antiga, mas existe uma maneira mais elegante de remover duplicatas em um
NSArray
caso você não se importe com o pedido .Se usarmos Operadores de Objetos da Key Value Coding , podemos fazer o seguinte:
Como a AnthoPak também observou, é possível remover duplicatas com base em uma propriedade. Um exemplo seria:
@distinctUnionOfObjects.name
fonte
@distinctUnionOfObjects.property
para remover duplicatas por propriedade de uma matriz de objetos personalizados. Por exemplo@distinctUnionOfObjects.name
Sim, o uso do NSSet é uma abordagem sensata.
Para adicionar à resposta de Jim Puls, aqui está uma abordagem alternativa para remover duplicatas, mantendo a ordem:
É essencialmente a mesma abordagem que a de Jim, mas copia itens exclusivos para uma nova matriz mutável, em vez de excluir duplicatas do original. Isso o torna um pouco mais eficiente de memória no caso de uma matriz grande com muitas duplicatas (não é necessário fazer uma cópia de toda a matriz) e, na minha opinião, é um pouco mais legível.
Observe que, em ambos os casos, verificar se um item já está incluído na matriz de destino (usando
containsObject:
no meu exemplo ouindexOfObject:inRange:
no de Jim) não é adequado para grandes matrizes. Essas verificações são executadas no tempo O (N), o que significa que, se você dobrar o tamanho da matriz original, cada verificação levará o dobro do tempo para ser executada. Como você está fazendo a verificação de cada objeto na matriz, também estará executando mais dessas verificações mais caras. O algoritmo geral (tanto o meu quanto o de Jim) é executado no tempo O (N 2 ), que fica caro rapidamente à medida que a matriz original cresce.Para reduzir o tempo O (N), você pode usar um
NSMutableSet
para armazenar um registro de itens já adicionados à nova matriz, pois as pesquisas do NSSet são O (1) e não O (N). Em outras palavras, verificar se um elemento é membro de um NSSet leva o mesmo tempo, independentemente de quantos elementos estiverem no conjunto.Código usando essa abordagem seria algo como isto:
Isso ainda parece um pouco inútil; ainda estamos gerando uma nova matriz quando a pergunta deixou claro que a matriz original é mutável, para que possamos redimensioná-la no local e economizar memória. Algo assim:
ATUALIZAÇÃO : Yuri Niyazov apontou que a minha última resposta na verdade é executado em O (N 2 ), porque
removeObjectAtIndex:
provavelmente é executado em O (N) tempo.(Ele diz "provavelmente" porque não sabemos ao certo como é implementado; mas uma implementação possível é que, após excluir o objeto no índice X, o método percorre todos os elementos do índice X + 1 até o último objeto na matriz , movendo-os para o índice anterior. Se for esse o caso, esse é realmente o desempenho de O (N).)
Então o que fazer? Depende da situação. Se você possui uma matriz grande e espera apenas um pequeno número de duplicatas, a desduplicação no local funcionará perfeitamente e poupará a criação de uma matriz duplicada. Se você tem uma matriz em que espera muitas duplicatas, a criação de uma matriz separada e com dupagem é provavelmente a melhor abordagem. A conclusão aqui é que a notação big-O apenas descreve as características de um algoritmo, não lhe dirá definitivamente qual é o melhor para qualquer circunstância.
fonte
Se você está segmentando o iOS 5 ou superior (que abrange todo o mundo do iOS), use melhor
NSOrderedSet
. Ele remove duplicatas e mantém a ordem do seuNSArray
.Apenas faça
Agora você pode convertê-lo novamente em um NSArray exclusivo
Ou apenas use o ordersSet porque ele possui os mesmos métodos, como um NSArray
objectAtIndex:
,firstObject
e assim por diante.Uma verificação de associação
contains
é ainda mais rápida noNSOrderedSet
que seria em umNSArray
Para mais informações, consulte a Referência NSOrderedSet
fonte
Disponível no OS X v10.7 e posterior.
Se você está preocupado com o pedido, a maneira certa de fazer
Aqui está o código para remover valores duplicados do NSArray no pedido.
fonte
precisa de ordem
ou não precisa de ordem
fonte
Aqui eu removi valores de nome duplicados do mainArray e armazene o resultado no NSMutableArray (listOfUsers)
fonte
Observe que, se você tiver uma matriz classificada, não precisará verificar todos os outros itens da matriz, apenas o último item. Isso deve ser muito mais rápido do que comparar com todos os itens.
Parece que as
NSOrderedSet
respostas sugeridas também exigem muito menos código, mas se você não puder usar umNSOrderedSet
por algum motivo e tiver uma matriz classificada, acredito que minha solução seria a mais rápida. Não tenho certeza de como ele se compara à velocidade dasNSOrderedSet
soluções. Observe também que meu código está sendo verificadoisEqualToString:
, para que a mesma série de letras não apareça mais de uma veznewArray
. Não tenho certeza se oNSOrderedSet
soluções removerão duplicatas com base no valor ou no local da memória.Meu exemplo assume que
sortedSourceArray
contém apenasNSString
s, apenasNSMutableString
s ou uma mistura dos dois. Se, emsortedSourceArray
vez disso, contiver apenasNSNumber
s ou apenasNSDate
s, você poderá substituircom
e deve funcionar perfeitamente. Se
sortedSourceArray
contiver uma mistura deNSString
s, seNSNumber
/ ouNSDate
s, provavelmente ocorrerá um erro fatal.fonte
Há um operador de objeto KVC que oferece uma solução mais elegante.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
Aqui está uma categoria do NSArray .fonte
Mais uma maneira simples de testar, que não adicionará Valor duplicado antes de adicionar objeto na matriz: -
// Suponha que mutableArray esteja alocado e inicialize e contenha algum valor
fonte
Remover valores duplicados do NSMutableArray no Objective-C
fonte
Aqui está o código para remover valores duplicados do NSMutable Array. . funcionará para você. myArray é sua matriz mutável que você deseja remover valores duplicados.
fonte
Usar
Orderedset
fará o truque. Isso manterá as duplicatas removidas da matriz e manterá a ordem que os conjuntos normalmente não fazemfonte
basta usar este código simples:
como o nsset não permite valores duplicados e todos os objetos retornam uma matriz
fonte
NSOrderedSet
insteed deNSSet
.