Como classificar uma matriz de números inteiros corretamente

848

Tentar obter o valor mais alto e mais baixo de uma matriz que eu sei que conterá apenas números inteiros parece ser mais difícil do que eu pensava.

var numArray = [140000, 104, 99];
numArray = numArray.sort();
alert(numArray)

Eu esperava que isso mostrasse 99, 104, 140000. Em vez disso, mostra 104, 140000, 99. Parece que o tipo está lidando com os valores como strings.

Existe uma maneira de obter a função de classificação para realmente classificar no valor inteiro?

peirix
fonte
10
Observe que nenhuma das respostas principais lida com todos os valores de ponto flutuante corretamente; em particular, nenhum deles manipula NaN. Seria bom ver uma resposta altamente classificada que lida com NaN.
Quuxplusone
3
BTW, se você estiver classificando muitos e muitos números inteiros, será vantajoso usar um algoritmo de classificação inteiro, como contagem de classificação . A classificação da contagem de tempo levará para executar escalas linearmente com o tamanho da sua matriz: O (n). Considerando que todas as soluções aqui usam classificação de comparação que é menos eficiente: O (n * log n).
Web_Designer 8/17
1
A classificação de contagem do @Web_Designer é linear em relação ao intervalo de números, não à matriz. Por exemplo, a triagem [1,1000000] levará mais de 2 passos, uma vez que o algoritmo terá de digitalizar cada índice de matriz entre 1 e 1000000, para ver qual célula de valor é maior do que 0.
yters
2
@yters Usando um hashmap, você pode prestar atenção apenas aos números inteiros que aparecem na matriz que está sendo classificada. Isso torna a classificação linear no tamanho da matriz.
21718 Kevin
1
a maneira mais rápida é usar o módulo de matriz de classificação isomórfica que funciona nativamente no navegador e no nó, suportando qualquer tipo de entrada, campos calculados e ordens de classificação personalizadas.
Lloyd

Respostas:

1236

Por padrão, o método de classificação classifica os elementos em ordem alfabética. Para classificar numericamente, basta adicionar um novo método que lide com classificações numéricas (sortNumber, mostrado abaixo) -

var numArray = [140000, 104, 99];
numArray.sort(function(a, b) {
  return a - b;
});

console.log(numArray);

No ES6, você pode simplificar isso com as funções de seta:

numArray.sort((a, b) => a - b); // For ascending sort
numArray.sort((a, b) => b - a); // For descending sort

Documentação:

A Mozilla Array.prototype.sort()recomenda essa função de comparação para matrizes que não contêm Infinity ou NaN. (PorqueInf - Inf é NaN, não 0).

Também exemplos de classificação de objetos por chave.

aks
fonte
148
Agradável. Mas não há realmente nenhuma maneira imediata de obter uma classificação numérica de javascript?
Peirix
39
ahah isso está fora da caixa! Mas se você for realmente impraticável, poderá vincular funções à classe da classe array no início do seu javascript: // Array.prototype.sortNormal = function () {retorne this.sort (function (a, b) {retorne um - b})} // Agora chamando .sortNormal () em qualquer matriz vai classificá-lo numericamente
Jack Franzen
13
Por que ab e não a> b. Eu sugiro que o último, a fim de erros da máquina operação evitar
Luca Davanzo
35
@Velthune A função de comparação deve retornar -1, 0 ou +1. a> b retornará apenas verdadeiro ou falso.
Iván Pérez
48
Este código pode ser reduzido usando uma função de seta . numberArray.sort((a, b) => (a - b));Yay! Eu acho que isso está próximo do caminho imediato. Nota: verifique se o seu mecanismo JS suporta Arrow Functions.
Jun
174

Baseando-se em todas as respostas acima, elas também podem ser feitas em uma linha como esta:

var numArray = [140000, 104, 99];

// ES5
numArray = numArray.sort(function (a, b) {  return a - b;  });

// ES2015
numArray = numArray.sort((a, b) => a - b);

//outputs: 99, 104, 140000
MarzSocks
fonte
8
@bodyflex Fixo: var arr = [140000, 104, 99].sort(function(a,b) { return a-b; });. Ou mais compacto, no ES6let arr = [140000, 104, 99].sort((a,b) => a-b);
00500005
1
Como eu disse em um comentário acima, as funções de seta são um ajuste inadequado aqui e eu desencorajaria qualquer um de usá-las dessa maneira. Você está usando um efeito colateral da sintaxe da seta para cortar as palavras functione return, mas na verdade não está usando o verdadeiro objetivo da função da seta de passar this. Esse código implica que há alguma thispassagem de contexto acontecendo, mas não existe. Confuso para outros desenvolvedores lerem seu código, apenas para salvar alguns caracteres. Não dependa de efeitos colaterais - codifique com propósito!
bambery
12
@bambery Eu não acho que você precisa usar uma função de seta exclusivamente para mudanças de contexto ...
Ted Morin
7
@ Kambery, você realmente entende mal o que a função de seta está fazendo. Você acha que, de alguma forma, passa thispara a função, mas isso não é verdade. Na verdade, ele negligencia a criação de uma variável thise a argumentsque geralmente substitui as variáveis ​​pai. A única razão pela qual você pode usar thisdentro de uma função de seta é o escopo lexical.
Cuta
2
@bambery que não envelheceu bem ... três anos depois e o desenvolvimento moderno de javascript usa funções de seta quase exclusivamente. :)
Kip,
71

array.sort faz uma classificação lexicográfica por padrão; para uma classificação numérica, forneça sua própria função. Aqui está um exemplo simples:

function compareNumbers(a, b)
{
    return a - b;
}

numArray.sort(compareNumbers);

Observe também que a classificação funciona "no local", não há necessidade da atribuição.

Paul Dixon
fonte
Eu não entendi o código acima, como "return a-b" faz a classificação ascendente?
vikramvi
se a <b, compareNumbers retorna um número negativo. Se a> b, será positivo. Se for igual, retorna 0.
Paul Dixon
38

Essa resposta é equivalente a algumas das respostas existentes, mas as funções de seta do ECMAScript 6 fornecem uma sintaxe muito mais compacta que nos permite definir uma função de classificação em linha sem sacrificar a legibilidade:

numArray = numArray.sort((a, b) => a - b);

É suportado na maioria dos navegadores hoje .

jjjjs
fonte
1
"sem sacrificar a legibilidade". Isso é subjetivo. Com alguns números inteiros simples, é legível. Ao trabalhar com objetos mais complexos e você deseja classificar em uma propriedade, não muito.
Tristan
3
@Tristan, a classificação na propriedade de um objeto ainda pode ser feita de maneira bastante limpa usando esta sintaxe. Se a propriedade do objeto que você deseja classificar é um número que você pode fazer: objArray=objArray.sort((a,b)=>a.numProperty - b.numProperty);e se a propriedade é uma string que você pode fazer: objArray=objArray.sort((a,b)=>a.strProperty.localeCompare(b.strProperty))‌​;Dito isto, esta questão pede especificamente sobre como classificar um array de inteiros
jjjjs
34

Estou surpreso por que todo mundo recomenda passar uma função de comparador sort(), o que torna a classificação realmente lenta!

Para classificar números, basta criar qualquer TypedArray :

var numArray = new Uint32Array([140000, 104, 99]);
numArray = numArray.sort();
alert(numArray)

dy_
fonte
4
O uso de um TypedArray acelera a classificação em cerca de 5X. Se você quiser ir ainda mais rápido, o pacote npm-algoritmos hpc implementa o Radix Sort e o Counting Sort que várias respostas aqui sugerem.
DragonSpit 10/08/19
uau, não sabia que isso existia!
pixelearth
21

A razão pela qual a função de classificação se comporta tão estranha

A partir da documentação :

[...] a matriz é classificada de acordo com o valor do ponto de código Unicode de cada caractere, de acordo com a conversão de cadeia de cada elemento.

Se você imprimir os valores de ponto unicode da matriz, isso ficará claro.

console.log("140000".charCodeAt(0));
console.log("104".charCodeAt(0));
console.log("99".charCodeAt(0));

//Note that we only look at the first index of the number "charCodeAt(  0  )"

Isso retorna: "49, 49, 57".

49 (unicode value of first number at 140000)
49 (unicode value of first number at 104)
57 (unicode value of first number at 99)

Agora, como 140000 e 104 retornaram os mesmos valores (49), ele corta o primeiro índice e verifica novamente:

console.log("40000".charCodeAt(0));
console.log("04".charCodeAt(0));

//Note that we only look at the first index of the number "charCodeAt(  0  )"

52 (unicode value of first number at 40000)
40 (unicode value of first number at 04)

Se classificarmos isso, obteremos:

40 (unicode value of first number at 04)
52 (unicode value of first number at 40000)

então 104 vem antes de 140000.

Portanto, o resultado final será:

var numArray = [140000, 104, 99];
numArray = numArray.sort();
console.log(numArray)

104, 140000, 99

Conclusão:

sort()faz a classificação olhando apenas para o primeiro índice dos números. sort()não se importa se um número inteiro é maior que outro, ele compara o valor do unicode dos dígitos e, se houver dois valores iguais de unicode, verifica se existe um próximo dígito e o compara também.

Para classificar corretamente, você precisa passar uma função de comparação, sort()como explicado aqui .

Preto
fonte
Dica: esta é apenas a minha explicação, na verdade, não procurei o código. Portanto, não confie totalmente nesta resposta.
Preto
17

Eu concordo com aks, no entanto, em vez de usar

return a - b;

Você deveria usar

return a > b ? 1 : a < b ? -1 : 0;
user3587638
fonte
18
Você pode explicar por que alguém deveria usar sua operação ternária mais ilegível? Tanto quanto eu posso dizer, teria o mesmo resultado.
stefannew
6
Essa resposta também leva em consideração valores iguais e os deixa no mesmo lugar.
Maarten00
23
E a - b não?
Bryan Rayner
12
"return ab" pode ser adequado para o caso específico desta questão (javascript e todos os itens de entrada conhecidos como ints), mas pessoalmente prefiro a forma ternária porque é mais canônica - funciona em mais casos, em mais linguagens de programação , com mais tipos de dados. Por exemplo, em C, ab pode transbordar, levando ao tipo de loop infinito, corrompendo memória, travando, etc. Dito isso, mesmo a forma ternária não funcionará bem se houver NaNs ou tipos mistos envolvidos.
Don Hatch
8
O >e <ainda comparam aeb como strings.
vriesdemichael
11

No novo mundo ES6, é muito mais fácil fazer uma espécie

numArray.sort((a,b) => a-b);

Isso é tudo que você precisa :)

Chait
fonte
10

No JavaScript, o comportamento padrão do método sort () é classificar valores em uma matriz em ordem alfabética.

Para classificar por número, você deve definir uma função de classificação numérica (o que é muito fácil):

...
function sortNumber(a, b)
{
  return a - b;
}

numArray = numArray.sort(sortNumber);
Peter Mortensen
fonte
8

Array.prototype.sort () é o método go para classificar matrizes, mas há alguns problemas que precisamos estar cientes.

A ordem de classificação é, por padrão, lexicográfica e não numérica, independentemente dos tipos de valores na matriz. Mesmo se a matriz tiver todos os números, todos os valores serão convertidos em sequência e classificados lexicograficamente.

Então, precisamos personalizar o método sort () e reverse () como abaixo.

URL referido

Para classificar números dentro da matriz

numArray.sort(function(a, b)
{
    return a - b;
});

Para reverter números dentro da matriz

numArray.sort(function(a, b)
{
    return b - a;
});

URL referido

Merbin Joe
fonte
6

A questão já foi respondida, a maneira mais curta é usar o sort()método. Mas se você estiver procurando por mais maneiras de classificar sua matriz de números e também adora ciclos, verifique o seguinte

Classificação de inserção

Crescente:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length; i++) {
    var target = numArray[i];
    for (var j = i - 1; j >= 0 && (numArray[j] > target); j--) {
        numArray[j+1] = numArray[j];
    }
    numArray[j+1] = target
}
console.log(numArray);

Descendente:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length; i++) {
    var target = numArray[i];
    for (var j = i - 1; j >= 0 && (numArray[j] < target); j--) {
        numArray[j+1] = numArray[j];
    }
    numArray[j+1] = target
}
console.log(numArray);

Tipo de seleção:

Crescente:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < numArray.length; j++) {
        if (numArray[j] < numArray[min]) {
            min = j;
        }
    }
    if (min != i) {
        var target = numArray[i];
        numArray[i] = numArray[min];
        numArray[min] = target;
    }
}
console.log(numArray);

Descendente:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < numArray.length; j++) {
        if (numArray[j] > numArray[min]) {
            min = j;
        }
    }
    if (min != i) {
        var target = numArray[i];
        numArray[i] = numArray[min];
        numArray[min] = target;
    }
}
console.log(numArray);

Diverta-se

Suicídio Comercial
fonte
Algum deles é realmente mais rápido para matrizes minúsculas do que o uso sort()em um TypedArray como esta resposta sugere . Certamente eles não serão mais rápidos para matrizes de médio a grande porte, porque esses são algoritmos O (n ^ 2).
Peter Cordes
5

A função 'numericamente' abaixo serve para classificar a matriz de números numericamente em muitos casos, quando fornecida como uma função de retorno de chamada:

function numerically(a, b){
    return a-b;
}

array.sort(numerically); 

Mas, em alguns casos raros, em que a matriz contém números muito grandes e negativos, pode ocorrer um erro de estouro, pois o resultado de ab fica menor que o menor número com o qual o JavaScript pode lidar.

Portanto, uma maneira melhor de escrever numericamente a função é a seguinte:

function numerically(a, b){
   if(a < b){
      return -1;
   } else if(a > b){
      return 1;
   } else {
      return 0;
   }
}
leet101
fonte
1
Os números JavaScript são de ponto flutuante. O IEEE754 define regras de estouro e subfluxo, incluindo transbordo para + -Infinity e subfluxo para subnormal ou + -0,0. Eu não acho que a subtração de dois números possa transbordar para + -0,0, mesmo que sejam grandes e próximos iguais. A diferença entre dois duplos é sempre representável como outro duplo diferente de zero (a menos que transborde, como DBL_MIN - DBL_MAX), mas o sub-fluxo não é possível. O cancelamento catastrófico torna o resultado impreciso, perdendo a maioria de seus "dígitos significativos", mas a-bsempre será diferente de zero e terá o sinal certo para a! = B.
Peter Cordes
4

para lidar com indefinido, nulo e NaN: o nulo se comporta como 0, NaN e indefinido termina.

array = [3, 5, -1, 1, NaN, 6, undefined, 2, null]
array.sort((a,b) => isNaN(a) || a-b)
// [-1, null, 1, 2, 3, 5, 6, NaN, undefined]
Ali Khosro
fonte
3

Apenas para uma matriz normal de valores de elementos:

function sortArrayOfElements(arrayToSort) {
    function compareElements(a, b) {
        if (a < b)
            return -1;
        if (a > b)
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareElements);
}

e.g. 1:
var array1 = [1,2,545,676,64,2,24]
**output : [1, 2, 2, 24, 64, 545, 676]**

var array2 = ["v","a",545,676,64,2,"24"]
**output: ["a", "v", 2, "24", 64, 545, 676]**

Para uma matriz de objetos:

function sortArrayOfObjects(arrayToSort, key) {
    function compareObjects(a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareObjects);
}

e.g. 1: var array1= [{"name": "User4", "value": 4},{"name": "User3", "value": 3},{"name": "User2", "value": 2}]

**output : [{"name": "User2", "value": 2},{"name": "User3", "value": 3},{"name": "User4", "value": 4}]**
Umesh
fonte
2

Atualizar! Role até a parte inferior da resposta para obter um smartSortaditivo de suporte que oferece ainda mais diversão!
Classifica matrizes de qualquer coisa !

Minha forma favorita pessoal dessa função permite um parâmetro para Ascendente ou Descendente:

function intArraySort(c, a) {
    function d(a, b) { return b - a; }
    "string" == typeof a && a.toLowerCase();
    switch (a) {
        default: return c.sort(function(a, b) { return a - b; });
        case 1:
                case "d":
                case "dc":
                case "desc":
                return c.sort(d)
    }
};

Uso tão simples quanto:

var ara = function getArray() {
        var a = Math.floor(Math.random()*50)+1, b = [];
        for (i=0;i<=a;i++) b.push(Math.floor(Math.random()*50)+1);
        return b;
    }();

//    Ascending
intArraySort(ara);
console.log(ara);

//    Descending
intArraySort(ara, 1);
console.log(ara);

//    Ascending
intArraySort(ara, 'a');
console.log(ara);

//    Descending
intArraySort(ara, 'dc');
console.log(ara);

//    Ascending
intArraySort(ara, 'asc');
console.log(ara);

jsFiddle


Ou exemplo de snippet de código aqui!

function intArraySort(c, a) {
	function d(a, b) { return b - a }
	"string" == typeof a && a.toLowerCase();
	switch (a) {
		default: return c.sort(function(a, b) { return a - b });
		case 1:
		case "d":
		case "dc":
		case "desc":
		return c.sort(d)
	}
};

function tableExample() {
	var d = function() {
			var a = Math.floor(50 * Math.random()) + 1,
				b = [];
			for (i = 0; i <= a; i++) b.push(Math.floor(50 * Math.random()) + 1);
			return b
		},
		a = function(a) {
			var b = $("<tr/>"),
				c = $("<th/>").prependTo(b);
			$("<td/>", {
				text: intArraySort(d(), a).join(", ")
			}).appendTo(b);
			switch (a) {
				case 1:
				case "d":
				case "dc":
				case "desc":
					c.addClass("desc").text("Descending");
					break;
				default:
					c.addClass("asc").text("Ascending")
			}
			return b
		};
	return $("tbody").empty().append(a(), a(1), a(), a(1), a(), a(1), a(), a(1), a(), a(1), a(), a(1))
};

tableExample();
table { border-collapse: collapse; }
th, td { border: 1px solid; padding: .25em .5em; vertical-align: top; }
.asc { color: red; }
.desc { color: blue }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table><tbody></tbody></table>


.smartSort ('asc' | 'desc')

Agora divirta-se ainda mais com um método de classificação que classifica uma matriz cheia de vários itens! Atualmente, não abrange "associativo" (também conhecido como chave de cadeia), mas abrange todo tipo de valor! Não apenas classificará os vários valores ascou de descacordo, mas também manterá constante "posição" de "grupos" de valores. Em outras palavras; ints são sempre os primeiros, depois as strings, as matrizes (sim, estou tornando isso multidimensional!), os objetos (não filtrados, elemento, data) e, finalmente, indefinidos e nulos!

"Por quê?" você pergunta. Por que não!

Agora vem em 2 sabores! O primeiro deles requer navegadores mais recentes, pois ele usa Object.definePropertypara adicionar o método ao Array.protoypeobjeto. Isto permite a facilidade de naturais utilização, tais como: myArray.smartSort('a'). Se você precisa implementar em navegadores mais antigos ou simplesmente não gosta de modificar objetos nativos, role para baixo até a versão Somente método .

/* begin */
/* KEY NOTE! Requires EcmaScript 5.1 (not compatible with older browsers) */
;;(function(){if(Object.defineProperty&&!Array.prototype.smartSort){var h=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return a-b;if(/^stringstring$/ig.test(e))return a>b;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.smartSort("a");b instanceof Array&&b.smartSort("a");if(a instanceof Date&&b instanceof Date)return a-b;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=e.concat(g).smartSort("a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=[a[c],b[c]].smartSort("a"),a[c]==d[0]?-1:1;var f=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("a");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=[a.id,b.id].smartSort("a"),a.id==e[0]?1:-1;e=[a.tagName, b.tagName].smartSort("a");return a.tagName==e[0]?1:-1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);e.concat(g).smartSort("a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=[a[d].id,b[f].id].smartSort("a"),a[d].id==c[0]?-1:1;c=[a[d].tagName,b[f].tagName].smartSort("d"); return a[d].tagName==c[0]?1:-1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=[a[d],b[f]].smartSort("a"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element||!a.hasOwnProperty(d))return-1;if(!b.hasOwnProperty(d))return 1}c=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]>g[1]},k=function(a,b){if(null== a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return b-a;if(/^stringstring$/ig.test(e))return b>a;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.smartSort("d");b instanceof Array&&b.smartSort("d");if(a instanceof Date&&b instanceof Date)return b-a;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=e.concat(g).smartSort("a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=[a[c],b[c]].smartSort("d"),a[c]==d[0]?-1:1;var f=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=[a.id,b.id].smartSort("d"),a.id==e[0]?-1:1;e=[a.tagName,b.tagName].smartSort("d");return a.tagName==e[0]?-1:1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);e.concat(g).smartSort("a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=[a[d].id,b[f].id].smartSort("d"),a[d].id==c[0]?-1:1;c=[a[d].tagName,b[f].tagName].smartSort("d");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=[a[d],b[f]].smartSort("d"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element)return-1;if(!a.hasOwnProperty(d))return 1;if(!b.hasOwnProperty(d))return-1}c=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]<g[1]};Object.defineProperty(Array.prototype,"smartSort",{value:function(){return arguments&& (!arguments.length||1==arguments.length&&/^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))?this.sort(!arguments.length||/^a([sc]{2})?$/i.test(arguments[0])?h:k):this.sort()}})}})();
/* end */

jsFiddle Array.prototype.smartSort ('asc | desc')


O uso é simples! Primeiro faça uma matriz maluca como:

window.z = [ 'one', undefined, $('<span />'), 'two', null, 2, $('<div />', { id: 'Thing' }), $('<div />'), 4, $('<header />') ];
z.push(new Date('1/01/2011'));
z.push('three');
z.push(undefined);
z.push([ 'one', 'three', 'four' ]);
z.push([ 'one', 'three', 'five' ]);
z.push({ a: 'a', b: 'b' });
z.push({ name: 'bob', value: 'bill' });
z.push(new Date());
z.push({ john: 'jill', jack: 'june' });
z.push([ 'abc', 'def', [ 'abc', 'def', 'cba' ], [ 'cba', 'def', 'bca' ], 'cba' ]);
z.push([ 'cba', 'def', 'bca' ]);
z.push({ a: 'a', b: 'b', c: 'c' });
z.push({ a: 'a', b: 'b', c: 'd' });

Em seguida, basta classificá-lo!

z.smartSort('asc'); // Ascending
z.smartSort('desc'); // Descending

Apenas método

O mesmo que o anterior, exceto apenas como um método simples!

/* begin */
/* KEY NOTE! Method `smartSort` is appended to native `window` for global use. If you'd prefer a more local scope, simple change `window.smartSort` to `var smartSort` and place inside your class/method */
window.smartSort=function(){if(arguments){var a,b,c;for(c in arguments)arguments[c]instanceof Array&&(a=arguments[c],void 0==b&&(b="a")),"string"==typeof arguments[c]&&(b=/^a([sc]{2})?$/i.test(arguments[c])?"a":"d");if(a instanceof Array)return a.sort("a"==b?smartSort.asc:smartSort.desc)}return this.sort()};smartSort.asc=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return a-b;if(/^stringstring$/ig.test(e))return a> b;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.sort(smartSort.asc);b instanceof Array&&b.sort(smartSort.asc);if(a instanceof Date&&b instanceof Date)return a-b;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=smartSort(e.concat(g),"a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=smartSort([a[c], b[c]],"a"),a[c]==d[0]?-1:1;var f=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"a");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=smartSort([a.id,b.id],"a"),a.id==e[0]?1:-1;e=smartSort([a.tagName,b.tagName],"a");return a.tagName==e[0]?1:-1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);smartSort(e.concat(g), "a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=smartSort([a[d].id,b[f].id],"a"),a[d].id==c[0]?-1:1;c=smartSort([a[d].tagName,b[f].tagName],"a");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=smartSort([a[d],b[f]],"a"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1; if(b.hasOwnProperty(f)&&b[f]instanceof Element||!a.hasOwnProperty(d))return-1;if(!b.hasOwnProperty(d))return 1}c=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"a");return a[Object.keys(a)[0]]==c[0]?1:-1}g=[a,b].sort();return g[0]>g[1]};smartSort.desc=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return b-a;if(/^stringstring$/ig.test(e))return b>a;if(/(string|number){2}/ig.test(e))return/string/i.test(c)? 1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.sort(smartSort.desc);b instanceof Array&&b.sort(smartSort.desc);if(a instanceof Date&&b instanceof Date)return b-a;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=smartSort(e.concat(g),"a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=smartSort([a[c],b[c]],"d"),a[c]==d[0]?-1:1;var f=smartSort([a[Object.keys(a)[0]], b[Object.keys(b)[0]]],"d");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=smartSort([a.id,b.id],"d"),a.id==e[0]?-1:1;e=smartSort([a.tagName,b.tagName],"d");return a.tagName==e[0]?-1:1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);smartSort(e.concat(g),"a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&& b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=smartSort([a[d].id,b[f].id],"d"),a[d].id==c[0]?-1:1;c=smartSort([a[d].tagName,b[f].tagName],"d");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=smartSort([a[d],b[f]],"d"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element)return-1; if(!a.hasOwnProperty(d))return 1;if(!b.hasOwnProperty(d))return-1}c=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]<g[1]}
/* end */

Usar:

z = smartSort(z, 'asc'); // Ascending
z = smartSort(z, 'desc'); // Descending

Método jsFiddle smartSort (matriz, "asc | desc")

SpYk3HH
fonte
2

Tente este código:

HTML:

<div id="demo"></div>

Código JavaScript:

<script>
    (function(){
        var points = [40, 100, 1, 5, 25, 10];
        document.getElementById("demo").innerHTML = points;
        points.sort(function(a, b){return a-b});
        document.getElementById("demo").innerHTML = points;
    })();
</script>
Sunny SM
fonte
2

Experimente este código como abaixo

var a = [5, 17, 29, 48, 64, 21];
function sortA(arr) {
return arr.sort(function(a, b) {
return a - b;
})
;} 
alert(sortA(a));
user7125929
fonte
isso não é verdade?
user7125929
1
var numArray = [140000, 104, 99];
numArray = numArray.sort((a,b) => a-b);
alert(numArray)
Vardaman PK
fonte
4
Bem-vindo ao StackOverflow. Sua resposta é idêntica à resposta aceita. Você pode adicionar alguma explicação à sua resposta para dizer por que isso deve ser preferido em relação à resposta aceita?
Simply Ged
1

Embora não seja obrigatório em JavaScript, se você desejar retornar estritamente -1, 0 ou 1 (semelhante à maneira como o operador de nave espacial funciona em PHP), você poderá usá-lo .sort() compareFunctionMath.sign()

O compareFunctionabaixo retorna estritamente -1, 0 ou 1:

numArray.sort((a, b) => Math.sign(a - b));

Nota: Math.sign() não é suportado no Internet Explorer.

Grant Miller
fonte
0

Esta é a solução já proposta e aceita como método no protótipo Array:

Array.prototype.sortNumeric = function () {
    return this.sort((a, b) => a - b);
};
Array.prototype.sortNumericDesc = function () {
    return this.sort((a, b) => b - a);
};
Erro 404
fonte
0

O método de classificação converte elementos de matriz em sequência. Portanto, abaixo do caminho também funciona bem com números decimais com elementos de matriz.

let productPrices = [10.33, 2.55, 1.06, 5.77];
console.log(productPrices.sort((a,b)=>a-b));

E fornece o resultado esperado.

Anshul Chaurasia
fonte
0

Substituindo o método de classificação.

Array.prototype.sortInt = function(){
    this.sort(function(a,b){return a-b});
}


numbers = [12,8,21,5,1,34];
numbers.sortInt()
//output -> [1,5,8,12,21,34]
sandes
fonte
0

A função de classificação padrão é classificada na ordem do dicionário:

var ar = [10000,3,200];
console.log(ar.sort());
//it will sort like :=> [10000, 200, 3]

O exemplo acima não é o caso que queremos para números. Portanto, se você possui números inteiros e a função de classificação padrão não está funcionando (porque é classificada na ordem dos dicionários), é necessário implementar sua própria função:

var ar = [10000,3,-09,200];
function customSortHelpForNumber(number1, number2){
     return number1-number2;
}
console.log(ar.sort(customSortHelpForNumber));
//it will sort like :=> [3, 200, 10000]

Espero que você tenha uma pergunta em mente como isso funciona? Aqui, quando fornecemos um método na função de classificação, ele passa dois números por vez e se o número retornar

  • -ve valor ou 0, mantém o primeiro número em seu lugar
  • + você valoriza trocar o local.

Seguindo isso para todos os números, classifica a matriz do número inteiro.

Se você estiver usando o ES6, escreva uma função de seta:

console.log(ar.sort((num1,num2)=> num1-num2));
    //it will sort like :=> [3, 200, 10000]
JustIn
fonte
-1

Aqui está minha função de matriz de classificação na biblioteca de utilitários:

sortArray: function(array) {
    array.sort(function(a, b) {
        return a > b;
    });
},

# Let's test a string array
var arr = ['bbc', 'chrome', 'aux', 'ext', 'dog'];
utils.sortArray(arr);
console.log(arr);
>>> ["aux", "bbc", "chrome", "dog", "ext", remove: function]

# Let's test a number array
var arr = [55, 22, 1425, 12, 78];
utils.sortArray(arr);
console.log(arr);
>>> [12, 22, 55, 78, 1425, remove: function]
fogo de artifício
fonte
3
Isso está errado! A função de classificação precisa retornar números negativos, 0 ou positivos, não verdadeiros ou falsos.
jperelli
Como o @jperelli mencionou, a função de classificação precisa que um número, não um booleano, seja retornado (e, considerando que existem três estados possíveis, iguais, acima e abaixo, é necessário ter uma classificação estável). Como sua resposta é declarada, ela não funciona. a-bdeve ser usado em seu lugar. (Você pode ser extravagante e fazer um Number(a>b)-0.5, no entanto, isso ainda não é um tipo estável).
ecc521