Javascript의 값으로 연관 배열을 정렬하는 방법은 무엇입니까?
연관 배열이 있습니다.
array["sub2"] = 1;
array["sub0"] = -1;
array["sub1"] = 0;
array["sub3"] = 1;
array["sub4"] = 0;
결과가 다음 순서로 각각의 인덱스가있는 배열이되는 값을 기준으로 정렬 (내림차순)하는 가장 우아한 방법은 무엇입니까?
sub2, sub3, sub1, sub4, sub0
?
자바 스크립트는 당신이 생각하는 "연관 배열"을 가지고 있지 않습니다. 대신 배열과 유사한 구문 (예제에서와 같이)을 사용하여 객체 속성을 설정하는 기능과 객체의 속성을 반복하는 기능이 있습니다.
이것의 결론은 속성을 반복 하는 순서 에 대한 보장이 없기 때문에 정렬과 같은 것이 없다는 것입니다. 대신 개체 속성을 "진정한"배열 (순서를 보장 함)로 변환해야합니다. 다음은 객체를 두 개의 튜플 (요소가 두 개인 배열)의 배열로 변환하고 설명하는대로 정렬 한 다음 반복하는 코드 조각입니다.
var tuples = [];
for (var key in obj) tuples.push([key, obj[key]]);
tuples.sort(function(a, b) {
a = a[1];
b = b[1];
return a < b ? -1 : (a > b ? 1 : 0);
});
for (var i = 0; i < tuples.length; i++) {
var key = tuples[i][0];
var value = tuples[i][1];
// do something with key and value
}
콜백을받는 함수로 래핑하는 것이 더 자연 스러울 수 있습니다.
function bySortedValue(obj, callback, context) {
var tuples = [];
for (var key in obj) tuples.push([key, obj[key]]);
tuples.sort(function(a, b) {
return a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0
});
var length = tuples.length;
while (length--) callback.call(context, tuples[length][0], tuples[length][1]);
}
bySortedValue({
foo: 1,
bar: 7,
baz: 3
}, function(key, value) {
document.getElementById('res').innerHTML += `${key}: ${value}<br>`
});
<p id='res'>Result:<br/><br/><p>
'연관 배열'의 의미를 수정하는 대신 이것이 원하는 것이라고 생각합니다.
function getSortedKeys(obj) {
var keys = keys = Object.keys(obj);
return keys.sort(function(a,b){return obj[b]-obj[a]});
}
위해 정말 오래된 브라우저 , 대신를 사용 :
function getSortedKeys(obj) {
var keys = []; for(var key in obj) keys.push(key);
return keys.sort(function(a,b){return obj[b]-obj[a]});
}
당신은 (당신과 같은) 객체를 덤프하고 키 배열을 가져옵니다-eh 속성-다시, eh, 값, eh, 객체의 (숫자) 값에 따라 내림차순으로 정렬됩니다.
값이 숫자 인 경우에만 작동합니다. Tweek는 function(a,b)
정렬 메커니즘을 변경하여 오름차순으로 작동하거나 string
값에 대해 작동 합니다 (예 :). 독자를위한 연습 문제로 남았습니다.
값을 기준으로 (연관) 배열을 정렬하는 방법에서 다루는 계속되는 토론 및 기타 솔루션 가장 좋은 해결책은 (내 경우에) saml (아래 인용)입니다.
배열에는 숫자 인덱스 만있을 수 있습니다. 이것을 Object 또는 Array of Objects로 다시 작성해야합니다.
var status = new Array();
status.push({name: 'BOB', val: 10});
status.push({name: 'TOM', val: 3});
status.push({name: 'ROB', val: 22});
status.push({name: 'JON', val: 7});
status.push
방법 이 마음에 들면 다음과 같이 정렬 할 수 있습니다.
status.sort(function(a,b) {
return a.val - b.val;
});
실제로 JavaScript에는 "연관 배열"과 같은 것이 없습니다. 당신이 가진 것은 단지 평범한 오래된 물건입니다. 물론 그들은 일종의 연관 배열처럼 작동하며 키는 사용할 수 있지만 키 순서에 대한 의미는 없습니다.
객체를 객체 배열 (키 / 값 쌍)로 바꾸고 정렬 할 수 있습니다.
function sortObj(object, sortFunc) {
var rv = [];
for (var k in object) {
if (object.hasOwnProperty(k)) rv.push({key: k, value: object[k]});
}
rv.sort(function(o1, o2) {
return sortFunc(o1.key, o2.key);
});
return rv;
}
그런 다음 비교기 기능으로 호출합니다.
튜플이 마음에 들지 않으면 벤 블랭크의 대답을 변형 한 것입니다.
이렇게하면 몇 개의 문자가 절약됩니다.
var keys = [];
for (var key in sortme) {
keys.push(key);
}
keys.sort(function(k0, k1) {
var a = sortme[k0];
var b = sortme[k1];
return a < b ? -1 : (a > b ? 1 : 0);
});
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
var value = sortme[key];
// Do something with key and value.
}
불필요한 합병증이 필요하지 않습니다 ...
function sortMapByValue(map)
{
var tupleArray = [];
for (var key in map) tupleArray.push([key, map[key]]);
tupleArray.sort(function (a, b) { return a[1] - b[1] });
return tupleArray;
}
나는 $ .each of jquery를 사용하지만 for 루프로 만들 수 있습니다. 개선 사항은 다음과 같습니다.
//.ArraySort(array)
/* Sort an array
*/
ArraySort = function(array, sortFunc){
var tmp = [];
var aSorted=[];
var oSorted={};
for (var k in array) {
if (array.hasOwnProperty(k))
tmp.push({key: k, value: array[k]});
}
tmp.sort(function(o1, o2) {
return sortFunc(o1.value, o2.value);
});
if(Object.prototype.toString.call(array) === '[object Array]'){
$.each(tmp, function(index, value){
aSorted.push(value.value);
});
return aSorted;
}
if(Object.prototype.toString.call(array) === '[object Object]'){
$.each(tmp, function(index, value){
oSorted[value.key]=value.value;
});
return oSorted;
}
};
이제 할 수 있습니다
console.log("ArraySort");
var arr1 = [4,3,6,1,2,8,5,9,9];
var arr2 = {'a':4, 'b':3, 'c':6, 'd':1, 'e':2, 'f':8, 'g':5, 'h':9};
var arr3 = {a: 'green', b: 'brown', c: 'blue', d: 'red'};
var result1 = ArraySort(arr1, function(a,b){return a-b});
var result2 = ArraySort(arr2, function(a,b){return a-b});
var result3 = ArraySort(arr3, function(a,b){return a>b});
console.log(result1);
console.log(result2);
console.log(result3);
여기에서 특정 사례에 대한 최선의 접근 방식은 제안 된 공통점 입니다. 현대 브라우저에서 작동하는 약간의 개선 사항은 다음과 같습니다.
// aao is the "associative array" you need to "sort"
Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});
This could apply easily and work great in the specific case here so you can do:
let aoo={};
aao["sub2"]=1;
aao["sub0"]=-1;
aao["sub1"]=0;
aao["sub3"]=1;
aao["sub4"]=0;
let sk=Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});
// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
// do something with sk[i] or aoo[sk[i]]
}
Besides of this, I provide here a more "generic" function you can use to sort even in wider range of situations and that mixes the improvement I just suggested with the approaches of the answers by Ben Blank (sorting also string values) and PopeJohnPaulII (sorting by specific object field/property) and lets you decide if you want an ascendant or descendant order, here it is:
// aao := is the "associative array" you need to "sort"
// comp := is the "field" you want to compare or "" if you have no "fields" and simply need to compare values
// intVal := must be false if you need comparing non-integer values
// desc := set to true will sort keys in descendant order (default sort order is ascendant)
function sortedKeys(aao,comp="",intVal=false,desc=false){
let keys=Object.keys(aao);
if (comp!="") {
if (intVal) {
if (desc) return keys.sort(function(a,b){return aao[b][comp]-aao[a][comp]});
else return keys.sort(function(a,b){return aao[a][comp]-aao[a][comp]});
} else {
if (desc) return keys.sort(function(a,b){return aao[b][comp]<aao[a][comp]?1:aao[b][comp]>aao[a][comp]?-1:0});
else return keys.sort(function(a,b){return aao[a][comp]<aao[b][comp]?1:aao[a][comp]>aao[b][comp]?-1:0});
}
} else {
if (intVal) {
if (desc) return keys.sort(function(a,b){return aao[b]-aao[a]});
else return keys.sort(function(a,b){return aao[a]-aao[b]});
} else {
if (desc) return keys.sort(function(a,b){return aao[b]<aao[a]?1:aao[b]>aao[a]?-1:0});
else return keys.sort(function(a,b){return aao[a]<aao[b]?1:aao[a]>aao[b]?-1:0});
}
}
}
You can test the functionalities trying something like the following code:
let items={};
items['Edward']=21;
items['Sharpe']=37;
items['And']=45;
items['The']=-12;
items['Magnetic']=13;
items['Zeros']=37;
//equivalent to:
//let items={"Edward": 21, "Sharpe": 37, "And": 45, "The": -12, ...};
console.log("1: "+sortedKeys(items));
console.log("2: "+sortedKeys(items,"",false,true));
console.log("3: "+sortedKeys(items,"",true,false));
console.log("4: "+sortedKeys(items,"",true,true));
/* OUTPUT
1: And,Sharpe,Zeros,Edward,Magnetic,The
2: The,Magnetic,Edward,Sharpe,Zeros,And
3: The,Magnetic,Edward,Sharpe,Zeros,And
4: And,Sharpe,Zeros,Edward,Magnetic,The
*/
items={};
items['k1']={name:'Edward',value:21};
items['k2']={name:'Sharpe',value:37};
items['k3']={name:'And',value:45};
items['k4']={name:'The',value:-12};
items['k5']={name:'Magnetic',value:13};
items['k6']={name:'Zeros',value:37};
console.log("1: "+sortedKeys(items,"name"));
console.log("2: "+sortedKeys(items,"name",false,true));
/* OUTPUT
1: k6,k4,k2,k5,k1,k3
2: k3,k1,k5,k2,k4,k6
*/
As I already said, you can loop over sorted keys if you need doing stuffs
let sk=sortedKeys(aoo);
// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
// do something with sk[i] or aoo[sk[i]]
}
Last, but not least, some useful references to Object.keys and Array.sort
Just so it's out there and someone is looking for tuple based sorts. This will compare the first element of the object in array, than the second element and so on. i.e in the example below, it will compare first by "a", then by "b" and so on.
let arr = [
{a:1, b:2, c:3},
{a:3, b:5, c:1},
{a:2, b:3, c:9},
{a:2, b:5, c:9},
{a:2, b:3, c:10}
]
function getSortedScore(obj) {
var keys = [];
for(var key in obj[0]) keys.push(key);
return obj.sort(function(a,b){
for (var i in keys) {
let k = keys[i];
if (a[k]-b[k] > 0) return -1;
else if (a[k]-b[k] < 0) return 1;
else continue;
};
});
}
console.log(getSortedScore(arr))
OUPUTS
[ { a: 3, b: 5, c: 1 },
{ a: 2, b: 5, c: 9 },
{ a: 2, b: 3, c: 10 },
{ a: 2, b: 3, c: 9 },
{ a: 1, b: 2, c: 3 } ]
@commonpike's answer is "the right one", but as he goes on to comment...
most browsers nowadays just support
Object.keys()
Yeah.. Object.keys()
is WAY better.
But what's even better? Duh, it's it in coffeescript
!
sortedKeys = (x) -> Object.keys(x).sort (a,b) -> x[a] - x[b]
sortedKeys
'a' : 1
'b' : 3
'c' : 4
'd' : -1
[ 'd', 'a', 'b', 'c' ]
'developer tip' 카테고리의 다른 글
PHP에서 변수로 명명 된 객체 속성에 어떻게 액세스 할 수 있습니까? (0) | 2020.09.23 |
---|---|
"설정"된 경우에만 실행되어야하는 "디버그 전용"코드 (0) | 2020.09.23 |
포토샵은 두 이미지를 어떻게 혼합합니까? (0) | 2020.09.23 |
대소 문자를 구분하지 않는 xpath contains () 가능? (0) | 2020.09.23 |
자바 스크립트 사전에서 키 컬렉션을 얻는 방법은 무엇입니까? (0) | 2020.09.23 |