Estou procurando uma boa maneira de achatar (dividir) uma lista de intervalos numéricos potencialmente sobrepostos. O problema é muito semelhante ao desta pergunta: A maneira mais rápida de dividir períodos de datas sobrepostos e muitos outros.
No entanto, os intervalos não são apenas números inteiros e estou procurando um algoritmo decente que possa ser facilmente implementado em Javascript ou Python, etc.
Dados de exemplo:
Solução de exemplo:
Desculpas se for uma duplicata, mas ainda estou para encontrar uma solução.
javascript
algorithms
python
Jollywatt
fonte
fonte
Respostas:
Caminhe da esquerda para a direita, usando uma pilha para acompanhar a cor em que está. Em vez de um mapa discreto, use os 10 números no seu conjunto de dados como pontos de interrupção.
Começando com uma pilha vazia e configurando
start
como 0, faça um loop até chegarmos ao fim:start
e empurre-a e todas as cores de classificação mais baixa na pilha. Na sua lista nivelada, marque o início dessa cor.start
e encontre o final da cor atualstart
o final dessa cor, retire-a da pilha e verifique a próxima cor com a classificação mais altastart
estiver dentro do intervalo da próxima cor, adicione-a à lista nivelada, começando emstart
.Este é um detalhamento mental, considerando seus dados de exemplo:
fonte
Esta solução parece a mais simples. (Ou pelo menos, o mais fácil de entender)
Tudo o que é necessário é uma função para subtrair dois intervalos. Em outras palavras, algo que dará isso:
O que é bastante simples. Em seguida, você pode simplesmente percorrer cada um dos intervalos, começando pelo mais baixo e, para cada um, subtrair todos os intervalos acima, por sua vez. E aí está.
Aqui está uma implementação do subtrator de intervalo no Python:
Usando esta função, o resto pode ser feito da seguinte maneira: (Um 'span' significa um intervalo, pois 'range' é uma palavra-chave Python)
Isso dá
[['red', [12.5, 13.8]], ['blue', [0.0, 2.0]], ['green', [2.0, 3.5]], ['green', [10.0, 12.0]], ['yellow', [3.5, 6.7]], ['orange', [6.7, 10.0]]]
, o que está correto.fonte
Se os dados realmente tiverem escopo semelhante aos dados de amostra, você poderá criar um mapa como este:
Depois, basta percorrer este mapa para gerar os intervalos
Para funcionar, os valores devem estar em um intervalo relativamente pequeno, como nos dados de amostra.
Editar: para trabalhar com carros alegóricos verdadeiros, use o mapa para gerar um mapeamento de alto nível e, em seguida, consulte os dados originais para criar os limites.
fonte
Aqui está uma solução relativamente simples no Scala. Não deve ser muito difícil portar para outro idioma.
apply
captura umSet
de todos os intervalos já aplicados, localiza as sobreposições e retorna um novo conjunto menos as sobreposições e mais o novo intervalo e os novos intervalos divididos.foldLeft
chama repetidamenteapply
com cada faixa de entrada.fonte
Basta manter um conjunto de intervalos classificados por início. Adicione um intervalo que cubra tudo (-oo .. + oo). Para adicionar um intervalo r:
fonte