JavaScript 개체에는 특성에 따라 순서가 저장되지 않습니다 (사양에 따라 다름). Firefox는 for...in
루프를 사용할 때 속성의 정의 순서를 유지하는 것으로 보입니다. 이 행동이 내가 의지 할 수있는 것입니까? 순서가 지정된 해시 유형을 구현하는 JavaScript 코드가 어딘가에 있습니까?JavaScript의 순서가 지정된 해시
답변
이 질문은 최고의 검색 결과로 나타납니다. 순서가 지정된 해시를 찾지 못한 후에이 작은 코프 스크립트를 작성했습니다. 다행히도이 페이지에 방문하는 사람들을 도울 것입니다.
## OrderedHash
# f = new OrderedHash
# f.push('a', 1)
# f.keys()
#
class OrderedHash
constructor: ->
@m_keys = []
@m_vals = {}
push: (k,v) ->
if not @m_vals[k]
@m_keys.push k
@m_vals[k] = v
length:() -> return @m_keys.length
keys:() -> return @m_keys
val: (k) -> return @m_vals[k]
vals:() -> return @m_vals
OP에서 JavaScript로 솔루션을 요청했습니다.> 내 포트는 아래를 참조하십시오. –
@FloLedermann 감사합니다. http://js2.coffee/도 이러한 상황에서 일반적으로 도움이 될 수 있습니다. – crizCraig
'@m_vals [k]'가 아니라면'm_keys' 배열에 키를 푸시하는 것처럼 보입니다. 아마도 if (! (k in this.m_vals))'(CoffeeScript를 모르기 때문에 그렇게 쓰는)해야 할 것입니다. –
아니요, Object type is specified to be an unordered collection of properties부터 사용할 수 없습니다. (또는 : 개체가 정렬되지 않은 속성 모음 인 경우에만 의존 할 수 있습니다.)
주문한 해시 세트를 원할 경우 직접 구현해야합니다.
운전하지 마십시오 downvotes 빨아? – Pointy
질문의 첫 부분 만 응답하고 해결책을 시도하지 않기 때문에 Downvoting –
트릭 중 하나는 규칙적인 순서가 지정되지 않은 해시에 데이터를 저장 한 다음 원하는 순서를 배열에 저장하는 것입니다. JS에서는 순서 배열을 해시 자체의 일부로 만들 수도 있습니다.
var myHash = {
a: "2",
b: "3",
c: "1"
};
myHash.order = [ myHash.c, myHash.a, myHash.b ];
alert("I can access values by key. Here's B: " + myHash.b);
var message = "I can access also loop over the values in order: ";
for (var i=0;i<myHash.order.length;i++)
{
message = message + myHash.order[i] + ", ";
}
alert(message)
세련된 것은 아니지만 작업이 완료됩니다.
이 솔루션은 주문에 사용 된 메커니즘이 캡슐화되지 않았고 클라이언트 코드가 내부적으로 작동하도록 알기 때문에 매우 취약합니다. ... 일회용 프로젝트는 괜찮지 만 생산 준비가 된 IMO는 아닐 수도 있습니다. –
실현이 늦었지만 다른 곳에서는 찾을 수 없었습니다. * UPDATE 열거 할 수없는 필수 메서드 및 속성을 추가했습니다. 빠른 ES 5 구현 (필요에 따라 polyfill) :
function orderedHash(object) {
'use strict'
var obj = object || {}
Object.defineProperties(this, {
'length': {
value: 0,
writable: true
},
'keys' : {
value: [],
writable: true
},
'sortedBy': {
value: '',
writable: true
}
})
this.hash(obj)
obj = null
}
Object.defineProperties(orderedHash.prototype, {
'sortByKeys': {
value: function sortByKeys() {
var i, len, name
this.keys.sort(function(a, b) {
return a >= b ? 1 : -1
})
for (i=0, len = this.keys.length; i < len; ++i) {
name = this.keys[i]
this[i] = this[name]
}
this.sortedBy = 'keys'
return null
}
},
'sortByValues': {
value: function sortByValues() {
var i, len, newIndex, name, ordered = [], names = this.keys.splice(0)
this.keys = []
for (i=0, len = this.length; i < len; ++i) {
ordered.push(this[i])
ordered.sort(function(a, b) {
return a >= b ? 1 : -1
})
newIndex = ordered.lastIndexOf(this[i])
name = names[i]
this.keys.splice(newIndex, 0 , name)
}
for (i=0, len = ordered.length; i < len; ++i) {
this[i] = ordered[i]
}
this.sortedBy = 'values'
return null
}
},
'insert': {
value: function insert(name, val) {
this[this.length] = val
this.length += 1
this.keys.push(name)
Object.defineProperty(this, name, {
value: val,
writable: true,
configurable: true
})
if (this.sortedBy == 'keys') {
this.sortByKeys()
} else {
this.sortByValues()
}
return null
}
},
'remove': {
value: function remove(name) {
var keys, index, i, len
delete this[name]
index = this.keys[name]
this.keys.splice(index, 1)
keys = Object.keys(this)
keys.sort(function(a, b) {
return a >= b ? 1 : -1
})
for (i=0, len = this.length; i < len; ++i) {
if (i >= index) {
this[i] = this[i + 1]
}
}
delete this[this.length - 1]
this.length -= 1
return null
}
},
'toString': {
value: function toString() {
var i, len, string = ""
for (i=0, len = this.length; i < len; ++i) {
string += this.keys[i]
string += ':'
string += this[i].toString()
if (!(i == len - 1)) {
string += ', '
}
}
return string
}
},
'toArray': {
value: function toArray() {
var i, len, arr = []
for (i=0, len = this.length; i < len; ++i) {
arr.push(this[i])
}
return arr
}
},
'getKeys': {
value: function getKeys() {
return this.keys.splice(0)
}
},
'hash': {
value: function hash(obj) {
var i, len, keys, name, val
keys = Object.keys(obj)
for (i=0, len = keys.length; i < len; ++i) {
name = keys[i]
val = obj[name]
this[this.length] = val
this.length += 1
this.keys.push(name)
Object.defineProperty(this, name, {
value: val,
writable: true,
configurable: true
})
}
if (this.sortedBy == 'keys') {
this.sortByKeys()
} else {
this.sortByValues()
}
return null
}
}
})
여기 어떻게됩니까 대신 할당의 Object.defineProperty()
를 사용하여 할 수있는 우리가 for...in
또는 Object.keys()
를 사용하여 해시를 반복 이렇게하면 속성이 아닌 열거 할 것입니다 우리 순서가 지정된 값만 가져 오지만 hash.propertyname
을 확인하면됩니다. 다른 객체 (hash()
)의 삽입, 제거, 동화, 키순 정렬, 값순 정렬, 배열 또는 문자열 변환, 원본 색인 이름 가져 오기 등의 메소드가 있습니다. 프로토 타입에 추가했지만 그 외에도 있습니다 -enumerable, for...in
루프는 여전히 작동합니다. 비 프리미티브에서 테스트하는 데 시간이 걸리지 않았지만 문자열, 숫자 등에서 정상적으로 작동합니다.
@Vardhan의 대답은 일반 JavaScript로, 클래식 OO 대신 클로저를 사용하고 삽입) 방법 :
function makeOrderedHash() {
var keys = [];
var vals = {};
return {
push: function(k,v) {
if (!vals[k]) keys.push(k);
vals[k] = v;
},
insert: function(pos,k,v) {
if (!vals[k]) {
keys.splice(pos,0,k);
vals[k] = v;
}
},
val: function(k) {return vals[k]},
length: function(){return keys.length},
keys: function(){return keys},
values: function(){return vals}
};
};
var myHash = makeOrderedHash();
매우 간단한 방법은 배열을 사용하여 주문을 저장하는 것입니다. 사용자 정의 비교 기능을 작성하여 필요한 순서를 설정해야합니다. 아래쪽은 배열을 정렬하고 관계를 추적 할 때마다 매번 해시 테이블을 변경해야합니다. 변경 해시 목록을 유지 관리해야하는 것은 그리 깔끔하지 않습니다. 당신이하는 특성이 삽입 된 주문 알에만 관심이 있다면
var order=[];
var hash={"h1":4,"h2":2,"h3":3,"h4":1};
function cmp(a,b) {
if (hash[a] < hash[b]) return -1;
if (hash[a] > hash[b]) return 1;
return 0;
}
// Add initial hash object to order array
for(i in hash) order.push(i);
order.sort(cmp);
// h4:1 h2:2 h3:3 h1:4
// Add entry
hash['h5']=2.5;
order.push('h5');
order.sort(cmp);
// h4:1 h2:2 h5:2.5 h3:3 h1:4
// Delete entry
order.splice(order.indexOf('h5'), 1);
delete hash['h5'];
// h4:1 h2:2 h3:3 h1:4
// Display ordered hash array (with keys)
for(i in order) console.log(order[i],hash[order[i]]);
, @Craig_Walker 솔루션을 촬영, 쉬운 솔루션은 다음과 같습니다 특히
var obj ={ }
var order = [];
function add(key, value) {
obj[key] = value;
order.push(key);
}
function getOldestKey() {
var key = order.shift();
return obj[key]
}
function getNewsetKey() {
var key = order.pop();
return obj[key]
}
자바 스크립트 2016, ECMA 스크립트 (6), 지원 Map
built-in class.
Map 객체는 요소를 삽입 순서대로 반복합니다. for ... of 루프는 각 반복마다 [key, value] 배열을 반환합니다.
그게 당신이 필요합니다. (즉하지만,이 데이터 구조에 대한 설명에서 처음으로 정보를 왜 궁금하다.) 예를 들어
,
m = new Map()
m.set(3,'three')
m.set(1,'one')
m.set(2,'two')
m // Map { 3 => 'three', 1 => 'one', 2 => 'two' }
[...m.keys()] // [ 3, 1, 2 ]
또는 docs에서 예 :
var myMap = new Map();
myMap.set(0, 'zero');
myMap.set(1, 'one');
myMap // Map { 0 => 'zero', 1 => 'one' }
for (var [key, value] of myMap) {
console.log(key + " = " + value);
}
for (var key of myMap.keys()) {
console.log(key);
}
for (var value of myMap.values()) {
console.log(value);
}
for (var [key, value] of myMap.entries()) {
console.log(key + " = " + value);
}
- 1. 순서가 지정된 해시 가져 오기
- 2. PHP : 순서가 지정된 디렉토리 목록
- 3. JavaScript의 큰 문자열과 해시 비교
- 4. 순서가 지정된 목록의 열거 형 또는 집합
- 5. BST에서 순서가 지정된 번호 순서 삭제
- 6. 순서가 지정된 배열의 배열을 효과적으로 정렬하는 방법
- 7. C#과 javascript의 guid에 대한 동일한 해시
- 8. 순서가 지정된 항복 형 파이썬 반복자 세트에 합치기
- 9. Ruby : 순서가 지정된 배열과 번호가있는 경우 다음 번호의 배열에 추가
- 10. LINQ/EF에서 순서가 지정된 쿼리로 IList를 반환하는 방법
- 11. (해시)는 javascript의 함수 매개 변수로 무엇인가 의미합니까?
- 12. 맵을 사용하여 지정된 값과 일치하는 (키, 값) 해시 세트를 추출합니다.
- 13. 30 초마다 지정된 해시 태그에서 트윗을 표시하거나 업데이트하는 방법
- 14. 할당 순서가
- 15. javascript의 file_Get_contents
- 16. JavaScript의 타이밍
- 17. JavaScript의 버그
- 18. JavaScript의 정수
- 19. javascript의 array.select()
- 20. JavaScript의 preg_match?
- 21. JavaScript의 SecureRandom?
- 22. perl의 해시 해시 문제
- 23. Perl 해시 함수의 해시
- 24. MongoDB BSON doc에서 키 순서가 중요합니까?
- 25. 테이블의 열 순서가 중요합니까?
- 26. FilterAttribute 순서가 작동하지 않습니다.
- 27. 컬렉션의 순서가 올바른지 확인하십시오.
- 28. WSDL 정렬 순서가 적절합니까?
- 29. 내레이터의 읽기 순서가 잘못되었습니다.
- 30. 속성의 순서가 어떤 보증을합니까?
페이지에 http : //stackoverflow.com/questions/280713/elements-order-for-in-loop-in-javascript –