Aqui eu tenho números inteiros 1:7
para quatro partições diferentes, ou seja, {1}, {2,3,4}, {5,6} e {7} e essas partições são escritas em uma lista, ou seja list(1,c(2,3,4),c(5,6),7)
,. Trato as partições como conjuntos, de modo que diferentes permutações de elementos em uma partição sejam reconhecidas como a mesma. Por exemplo, list(1,c(2,3,4),c(5,6),7)
e list(7,1,c(2,3,4),c(6,5))
são equivalentes.
Observe que, não há repetição para elementos na lista, por exemplo, não list(c(1,2),c(2,1),c(1,2))
, pois esse problema está discutindo partições exclusivas em todo o conjunto.
Listei algumas das diferentes permutações na lista lst
como abaixo
lst <- list(list(1,c(2,3,4),c(5,6),7),
list(c(2,3,4),1,7,c(5,6)),
list(1,c(2,3,4),7,c(6,5)),
list(7,1,c(3,2,4),c(5,6)))
e o que eu quero fazer é verificar se todas as permutações são equivalentes. Se sim, então obtemos resultado TRUE
.
O que eu fiz até agora é para classificar os elementos dentro de cada partição, e usado setdiff()
com interset()
e union()
julgá-lo (ver o meu código abaixo)
s <- Map(function(v) Map(sort,v),lst)
equivalent <- length(setdiff(Reduce(union,s),Reduce(intersect,s),))==0
No entanto, acho que esse método seria lento sempre que o tamanho da partição aumentar. Existe alguma abordagem mais rápida para fazer isso? Apreciado com antecedência!
- alguns casos de teste (dados pequenos)
# should return `TRUE`
lst1 <- list(list(1,c(2,3,4),c(5,6)),
list(c(2,3,4),1,c(5,6)),
list(1,c(2,3,4),c(6,5)))
# should return `TRUE`
lst2 <- list(list(1:2, 3:4), list(3:4, 1:2))
# should return `FALSE`
lst3 <- list(list(1,c(2,3,4),c(5,6)), list(c(2,3,4),1,c(5,6)), list(1,c(2,3,5),c(6,4)))
fonte
Map
chamadaslst_equal = list(list(1:2, 3:4), list(3:4, 1:2))
e também um onde o resultado deve serFALSE
, talvezlst_false <- list(list(1,c(2,3,4),c(5,6)), list(c(2,3,4),1,c(5,6)), list(1,c(2,3,5),c(6,4)))
FALSE
. Dessa forma, quando uma resposta funciona em alguns casos de teste, mas não em todos, é fácil diagnosticar o motivo. Quando há apenas um exemplo, você perde nuances nos resultados do teste. Também é bom adicionar novos exemplos em vez de alterar os exemplos existentes nas pessoas que já trabalharam neles.lst
for potencialmente longo, você poderá obter eficiência com outras abordagens. Por exemplo, um primeiro cheque quelength(unique(lengths(lst))) == 1
seria muito rapidamente voltarFALSE
se alguma das listas internas tem o número errado de elementos ....lst
, comparando-olst[[i]]
comlst[[1]]
, e assim você pode parar assim que encontrar uma incompatibilidade, em vez de fazer todas as comparações. Selst
é longoFALSE
es são comuns, isso pode ser um grande ganho de eficiência, mas provavelmente não vale a pena.Respostas:
Um post sobre
R
e qualquer variante do fast não está completo sem uma solução com o rcpp .Para maximizar a eficiência, escolher a estrutura de dados correta será de extrema importância. Nossa estrutura de dados precisa armazenar valores exclusivos e também ter acesso / inserção rápida. Isso é exatamente o que std :: unordered_set incorpora. Precisamos apenas determinar como podemos identificar exclusivamente cada um
vector
dos não-ordenadosintegers
.Entre no Teorema Fundamental da Aritmética
O TLC afirma que todo número pode ser representado exclusivamente (até a ordem dos fatores) pelo produto de números primos.
Aqui está um exemplo demonstrando como podemos usar o FTA para decifrar rapidamente se dois vetores são equivalentes até a ordem (NB
P
abaixo está uma lista de números primos ...(2, 3, 5, 7, 11, etc.)
:A partir disso, vemos
vec1
e mapeamosvec3
corretamente para o mesmo número, enquantovec2
são mapeados para um valor diferente.Como nossos vetores reais podem conter até cem números inteiros menores que 1000, a aplicação do FTA produzirá números extremamente grandes. Podemos contornar isso, aproveitando a regra do produto do logaritmo:
Com isso à nossa disposição, poderemos lidar com exemplos de números muito maiores (isso começa a se deteriorar em exemplos extremamente grandes).
Primeiro, precisamos de um gerador simples de números primos (NB: Na verdade, estamos gerando o log de cada número primo).
E aqui está a principal implementação:
Aqui estão os resultados, quando aplicados
lst1, lst2, lst3, & lst (the large one)
pelo @GKi.E aqui estão alguns benchmarks com o
units
conjunto de parâmetros pararelative
.Aproximadamente 3x mais rápido que a solução mais rápida já vista no exemplo maior.
Para mim, esse resultado
base R
mostra muito a beleza e a eficiência exibidas por @GKi, @ chinsoon12, @Gregor, @ThomasIsCoding e muito mais. Escrevemos cerca de 100 linhas de muito específicasC++
para obter uma velocidade moderada. Para ser justo, asbase R
soluções acabam chamando principalmente o código compilado e acabam utilizando tabelas de hash, como fizemos acima.fonte
Após a classificação, você pode usar
duplicated
eall
.Alternativa: classifique em um loop
Alternativa: classifique durante o loop e permita a saída antecipada
ou usando
setequal
ou melhorando um pouco a ideia de @ chinsoon12 para trocar a lista por um vetor!
ou evite o segundo
order
ou trocar
order
commatch
(oufmatch
)Ou sem saída antecipada.
ou escrito em C ++
Obrigado a @Gregor pelas dicas para melhorar a resposta!
fonte
lst <- list(list(1,c(2,3,4),c(5,6),7), list(c(2,3,4),1,7,c(5,6)), list(1,c(2,3,4),7,c(6,5)), list(7,1,c(3,2,4),c(5,6)))
será julgado comoFALSE
min
!Atuação:
Bibliotecas:
Funções:
Dados:
fonte
length(setdiff(Reduce(union,s),Reduce(intersect,s)))==0
, desculpe pelo meu erro ....Espero que a segunda vez com sorte
casos de teste:
Verificações:
código de temporização:
horários:
fonte