Eu tenho um número de menos 1000 a mais 1000 e tenho uma matriz com números. Como isso:
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
Eu quero que o número que eu tenho mude para o número mais próximo da matriz.
Por exemplo, recebo 80
o número que quero que ele obtenha 82
.
javascript
arrays
novato
fonte
fonte
x
, analise a matriz uma a uma, comparei
com o número atual na matriz, se a diferença entre ela ei
for menor que o valor atual emx
, definax
o número atual da matriz. Quando terminar,x
tem o número mais próximoi
da matriz.Respostas:
Versão ES5:
fonte
goal
para reduzir, você deve referenciá-lo de um escopo global.Aqui está o pseudocódigo que deve ser conversível em qualquer linguagem processual:
Ele simplesmente calcula as diferenças absolutas entre o número fornecido e cada elemento da matriz e devolve um deles com a diferença mínima.
Para os valores de exemplo:
Como prova de conceito, aqui está o código Python que eu usei para mostrar isso em ação:
E, se você realmente precisar dele em Javascript, veja abaixo um arquivo HTML completo que demonstra a função em ação:
Agora, lembre-se de que pode haver espaço para maior eficiência se, por exemplo, seus itens de dados forem classificados (que podem ser inferidos a partir dos dados de amostra, mas você não o declara explicitamente). Você pode, por exemplo, usar uma pesquisa binária para encontrar o item mais próximo.
Você também deve ter em mente que, a menos que precise fazer isso muitas vezes por segundo, as melhorias de eficiência serão praticamente imperceptíveis, a menos que seus conjuntos de dados fiquem muito maiores.
Se você não quiser experimentá-lo dessa forma (e pode garantir a matriz é classificada em ordem crescente), este é um bom ponto de partida:
Basicamente, usa bracketing e verificação do valor médio para reduzir pela metade o espaço da solução para cada iteração, um
O(log N)
algoritmo clássico , enquanto a pesquisa seqüencial acima foiO(N)
:Como afirmado, isso não deve fazer muita diferença para conjuntos de dados pequenos ou para coisas que não precisam ser extremamente rápidas, mas é uma opção que você deve considerar.
fonte
Versão ES6 (2015):
Para reutilização, você pode agrupar uma função curry que suporte espaços reservados ( http://ramdajs.com/0.19.1/docs/#curry ou https://lodash.com/docs#curry ). Isso oferece muita flexibilidade, dependendo do que você precisa:
fonte
Código de trabalho como abaixo:
fonte
Funciona com matrizes não ordenadas
Embora existam boas soluções postadas aqui, o JavaScript é uma linguagem flexível que nos fornece ferramentas para resolver um problema de várias maneiras diferentes. Tudo se resume ao seu estilo, é claro. Se o seu código for mais funcional, você encontrará a variação de redução adequada, ou seja:
No entanto, alguns podem achar isso difícil de ler, dependendo do estilo de codificação. Portanto, proponho uma nova maneira de resolver o problema:
Ao contrário de outras abordagens que encontram o valor mínimo usando
Math.min.apply
, essa não exige que a matriz de entradaarr
seja classificada . Não precisamos nos preocupar com os índices ou classificá-los com antecedência.Vou explicar o código linha por linha para maior clareza:
arr.map(function(k) { return Math.abs(k - x) })
Cria uma nova matriz, essencialmente armazenando os valores absolutos dos números fornecidos (número emarr
) menos o número de entrada (x
). Procuraremos o menor número a seguir (que também é o mais próximo do número de entrada)Math.min.apply(Math, indexArr)
Essa é uma maneira legítima de encontrar o menor número na matriz que acabamos de criar antes (nada mais)arr[indexArr.indexOf(min)]
Esta é talvez a parte mais interessante. Encontramos o menor número, mas não temos certeza se devemos adicionar ou subtrair o número inicial (x
). Isso porque costumávamosMath.abs()
encontrar a diferença. No entanto,array.map
cria (logicamente) um mapa da matriz de entrada, mantendo os índices no mesmo local. Portanto, para descobrir o número mais próximo, retornamos o índice do mínimo encontrado na matriz fornecidaindexArr.indexOf(min)
.Eu criei uma caixa demonstrando isso.
fonte
3n
o ES5, mesmo que você responda em 2016 e outras soluções sejam boas, mesmo que esse noob que fez essa pergunta claramente não fosse um programador na época.O(n)
solução executa cerca de 100k ops / s a menos que @paxdiabloO(log n)
em números aleatórios. Ao projetar um algoritmo, sempre classifique primeiro, eles dizem. (Exceto se você sabe o que está fazendo e você tem referências para suportá-lo.)const findClosest = goal => (a,b) => Math.abs(a - goal) < Math.abs(b - goal) ? a : b;
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362].reduce(findClosest(80))
Para matrizes classificadas (pesquisa linear)
Até agora, todas as respostas concentram-se na pesquisa em toda a matriz. Considerando que sua matriz já está classificada e você realmente deseja apenas o número mais próximo, essa é provavelmente a solução mais rápida:
Observe que o algoritmo pode ser amplamente aprimorado, por exemplo, usando uma árvore binária.
fonte
a[i]
oui[0]
.Todas as soluções são projetadas em excesso.
É tão simples quanto:
fonte
Essa solução usa o quantificador existencial ES5
Array#some
, que permite interromper a iteração, se uma condição for atendida.Ao contrário de
Array#reduce
, ele não precisa iterar todos os elementos para um resultado.Dentro do retorno de chamada, um absoluto
delta
entre o valor pesquisado e o valor realitem
é obtido e comparado com o último delta. Se maior ou igual, a iteração para, porque todos os outros valores com seus deltas são maiores que o valor real.Se o
delta
retorno de chamada for menor, o item real será atribuído ao resultado e o itemdelta
será salvolastDelta
.Por fim, valores menores com deltas iguais são obtidos, como no exemplo abaixo de
22
, que resulta em2
.Se houver uma prioridade de valores maiores, a verificação delta deverá ser alterada de:
para:
Isso ficaria com
22
o resultado42
(Prioridade de valores maiores).Esta função precisa de valores classificados na matriz.
Código com prioridade de valores menores:
Código com prioridade de maiores valores:
fonte
closestValue([ 2, 2, 42, 80 ], 50) === 2
ES6
Funciona com matrizes classificadas e não classificadas
Números Inteiros e Flutuantes, Cordas bem-vindas
Exemplos:
fonte
Não sei se devo responder a uma pergunta antiga, mas como esse post aparece primeiro nas pesquisas do Google, esperava que você me perdoasse adicionando minha solução e meus 2c aqui.
Sendo preguiçoso, não podia acreditar que a solução para essa pergunta seria um LOOP, então pesquisei um pouco mais e voltei com a função de filtro :
Isso é tudo !
fonte
goog.math.clamp
(fechamento do Google) apenas com matrizes e sem me preocupar com o limite inferior.Minha resposta a uma pergunta semelhante também é responsável por vínculos e é em Javascript puro, embora não use a pesquisa binária, por isso é O (N) e não O (logN):
https://stackoverflow.com/a/26429528/986160
fonte
Gosto da abordagem do Fusion, mas há um pequeno erro. Assim está correto:
Também é um pouco mais rápido, porque usa o melhorado
for
loop .No final, escrevi minha função assim:
Eu testei com
console.time()
e é um pouco mais rápido que a outra função.fonte
improved for loop
? Loops invertidos nem sempre são uma melhoria de desempenho..length
apenas uma vez, quando declarai
, e para esse loop. Mas eu acho quevar i = arr.length;while (i--) {}
seria ainda mais rápidowhile
. Agora é ainda mais rápido.Uma pesquisa binária ligeiramente modificada na matriz funcionaria.
fonte
Para um pequeno intervalo, a coisa mais simples é ter uma matriz de mapas, onde, por exemplo, a 80ª entrada teria o valor 82 nela, para usar seu exemplo. Para uma faixa muito maior e esparsa, provavelmente o caminho a seguir é uma pesquisa binária.
Com uma linguagem de consulta, você pode consultar valores a alguma distância de ambos os lados do seu número de entrada e depois classificar a lista reduzida resultante. Mas o SQL não tem um bom conceito de "próximo" ou "anterior", para fornecer uma solução "limpa".
fonte
Outra variante aqui é a faixa circular que conecta a cabeça aos pés e aceita apenas um valor mínimo para a entrada fornecida. Isso me ajudou a obter valores de código de char para um dos algoritmos de criptografia.
fonte
fonte
O mais eficiente seria uma pesquisa binária. No entanto, mesmo soluções simples podem sair quando o próximo número for uma correspondência adicional à atual . Quase todas as soluções aqui não levam em consideração que a matriz está ordenada e iterada por toda a coisa: /
Isso também pode ser executado em não-primitivos, por exemplo,
closest(data, 21, item => item.age)
Mude
find
parafindIndex
para retornar o índice na matriz.fonte
Para encontrar dois números mais próximos na matriz
fonte
Aqui está o trecho de código para encontrar o elemento mais próximo de um número de uma matriz na Complexidade O (nlog (n)): -
Entrada: - {1,60,0, -10,100,87,56} Elemento: - 56 Número mais próximo na matriz: - 60
Código fonte (Java):
fonte