키 / 값 쌍에 대한 Javascript의 객체 대 배열


83

매우 간단한 데이터 구조가 있다고 가정합니다.

(personId, name)

... 자바 스크립트 변수에 이들 중 다수를 저장하려고합니다. 내가보기에 세 가지 옵션이 있습니다.

// a single object
var people = {
    1 : 'Joe',
    3 : 'Sam',
    8 : 'Eve'
};

// or, an array of objects
var people = [
    { id: 1, name: 'Joe'},
    { id: 3, name: 'Sam'},
    { id: 8, name: 'Eve'}
];

// or, a combination of the two
var people = {
    1 : { id: 1, name: 'Joe'},
    3 : { id: 3, name: 'Sam'},
    8 : { id: 8, name: 'Eve'}
};

두 번째 또는 세 번째 옵션은 저장할 "값"부분이 둘 이상 (예 : 나이 등을 추가하는 것)이있는 경우에 갈 방법입니다. 이 구조에 더 이상 데이터 값이 필요하지 않다고 가정 해 보겠습니다. 어떤 것을 선택하고 그 이유는 무엇입니까?


편집 : 이제 예제는 가장 일반적인 상황 인 비 순차적 ID를 보여줍니다.


1
또한 2d 배열이 있습니다. var people = [[1, 'Joe'],[3, 'Sam'],[8,'Eve']];(id로 빠른 조회를 제공하지는 않지만 데이터를 저장하는 또 다른 옵션입니다)
User

답변:


58

각 솔루션에는 사용 사례가 있습니다.

일대일 관계 (예 : 단순 매핑)를 정의하려는 경우, 특히 키를 조회 키로 사용해야하는 경우 첫 번째 솔루션이 좋습니다.

두 번째 솔루션은 일반적으로 나에게 가장 강력하다고 느껴지며 빠른 조회 키가 필요하지 않은 경우 사용할 것입니다.

  • 자체 설명 적이므로 키가 사용자의 ID임을 알기 위해 사람을 사용하는 사람 에게 의존 할 필요가 없습니다 .
  • 각 개체는 독립적으로 제공되므로 데이터를 다른 곳으로 전달하는 데 더 좋습니다. 두 개의 매개 변수 (ID 및 이름) 대신 사람들에게 전달합니다.
  • 이것은 드문 문제이지만 때때로 키 값이 키로 사용하기에 유효하지 않을 수 있습니다. 예를 들어, 문자열 변환 (예 : ":"에서 ">")을 매핑하고 싶었지만 ":"는 유효한 변수 이름이 아니기 때문에 두 번째 방법을 사용해야했습니다.
  • 라인 어딘가에서 일부 (또는 모든) 사용자에게 더 많은 데이터를 추가해야하는 경우 쉽게 확장 할 수 있습니다. (죄송합니다. "논쟁을 위해서"에 대해 알고 있지만 이것은 중요한 측면입니다.)

세 번째는 빠른 조회 시간 + 위에 나열된 몇 가지 장점 (데이터 전달, 자체 설명)이 필요한 경우 유용합니다. 그러나 빠른 조회 시간이 필요하지 않으면 훨씬 더 번거 롭습니다. 또한 어느 쪽이든 객체의 ID가 어떻게 든 people 의 ID와 다르면 오류가 발생할 위험 있습니다.


1
세 번째 지점에서. 객체 속성은 이러한 문제를 피하기 위해 대괄호 표기법으로 액세스 할 수 있습니다. var x = { "ab> c ++": "foo"}; alert (x [ 'ab> c ++']);
nickf

속성이있는 예약어 몇 개에 문제가 있다고 생각합니다. 하지만 숫자를 사용할 때는 문제가 없습니다.
derobert

4
@derobert : 그렇게 생각하지 않습니다. x = { "삭제": 1, "for": 2, "기능": 3}; -이것은 유효하며 동일한 방법으로 액세스 할 수 있습니다.
nickf

7

실제로 네 번째 옵션이 있습니다.

var people = ['Joe', 'Sam', 'Eve'];

당신의 가치는 연속적이기 때문입니다. (물론 하나를 더하거나 빼야합니다 --- 아니면 그냥 첫 번째 요소로 undefined를 넣어야합니다).

개인적으로 (1) 또는 (3)과 함께 갈 것입니다. ID로 누군가를 찾는 것이 가장 빠르기 때문입니다 ( 최악의 경우 O log n ). (2)에서 id 3을 찾아야한다면 인덱스로 검색하거나 (이 경우 my (4)는 괜찮습니다) 검색해야합니다 — O (n).

설명 : O (log n )이 최악 이라고 말하는데 , AFAIK 및 구현은 해시 테이블 대신 균형 잡힌 트리를 사용하기로 결정할 수 있기 때문입니다. 최소 충돌을 가정하면 해시 테이블은 O (1)이됩니다.

nickf에서 편집 : 이후 OP의 예제를 변경 했으므로이 답변은 더 이상 의미가 없을 수 있습니다. 사과.

편집 후

자, 편집 후 옵션 (3)을 선택하겠습니다. 확장 가능하고 (새 속성을 쉽게 추가 할 수 있음) 빠른 조회가 가능하며 반복 할 수도 있습니다. 또한 필요한 경우 항목에서 ID로 돌아갈 수 있습니다.

옵션 (1)은 (a) 메모리를 절약해야하는 경우 유용합니다. (b) 개체에서 id로 다시 이동할 필요가 없습니다. (c) 저장된 데이터를 확장하지 않습니다 (예 : 그 사람의 성을 추가 할 수 없음).

(a) 주문을 보존해야하는 경우 옵션 (2)가 좋습니다. (b) 모든 요소를 ​​반복해야합니다. (c) id로 정렬되지 않는 한, id로 요소를 찾을 필요가 없습니다 (O (log n ) 에서 이진 검색을 할 수 있습니다 . 삽입 비용.


(1)과 (3)이 (2)보다 더 빠른 이유를 이해하지만 당분간 O (log (n))을 어떻게 얻었는지 궁금합니다. ID가 해시 테이블에 저장되어야하므로 O (1)이어야하지 않습니까?
Nathaniel Reinhart

해시 테이블 대신 균형 잡힌 트리를 사용하기로 결정한 구현을 볼 수 있었기 때문에 log n을 최악으로주었습니다. 물론 해시 테이블은 O (1) [충돌이 최소라고 가정]입니다.
derobert

ID는 항상 그렇게 단순하지는 않으며 순차 IRL이 거의 없기 때문에이를 지정해야합니다. 나는 그것이 가난하고 모호한 예임을 인정합니다.
nickf

+1, 귀하의 대답은 허용 된 것보다 나쁘지는 않습니다 ...하지만 네 번째 솔루션은 모든 데이터를 저장하지 않으므로 올바른 네 번째 옵션이 있습니다. var people = []; people[1] = 'Joe'; people[3] = 'Sam'; people[8] = 'Eve';또는 2 차원 배열로 : var people = []; people[1] = ['Joe', 'Smith']; people[3] = ['Sam', 'Miller']; people[8] = ['Eve', 'Sweet'];(예 : 'people [ 3] [1]; '은 모든 클래스 내부의 빠른 내부 데이터 저장에 매우 잘 작동합니다.
Marcus

...하지만 이것은 id가 정수인 경우에만 작동합니다. 그렇지 않으면 "전통적인"솔루션 2 ( for(var key in object)액세스로 유명한 것과 함께 )가 일반적인 경우 (O (n / 2) 포함) 또는 솔루션으로 이동하는 방법입니다. 3 당신이 O (1)을 가지고 있기 때문에 빠른 액세스를 위해 정말 큰 배열을 가지고 ... 그리고 마지막의 솔루션 1 위 잊어 할 경우,뿐만 아니라 당신의 ID가 정수뿐만 아니라, 경우에 ID가없는 정수없는 경우 : var people = {'Smith':'Joe', 'Miller':'Sam', 'Sweet': 'Eve' };( 다음과 같이 객체에 액세스해야하기 때문 alert(people.Smith);입니다. 정말 좋지 않습니다!).
Marcus

2

데이터가 절대 변경되지 않는다고 가정하면 첫 번째 (단일 개체) 옵션이 가장 좋습니다.

구조의 단순성은 파싱이 가장 빠르다는 것을 의미하며, 이와 같이 작고 거의 변경되지 않는 (또는 전혀) 변경되지 않는 데이터 세트의 경우 자주 실행될 것이라고 상상할 수 있습니다.이 경우 최소 오버 헤드는 잘 했어.


2

키 값 쌍을 관리하기 위해 작은 라이브러리를 만들었습니다.

https://github.com/scaraveos/keyval.js#readme

그것은 사용합니다

  • 빠른 삭제 및 값 검색 작업을 허용하는 키를 저장할 개체
  • 정말 빠른 값 반복을 허용하는 연결 목록

도움이되기를 바랍니다 :)


jsperf 링크를 추가하지 않는 이유는 무엇입니까?
Janus Troelsen 2013 년

그 도서관은 대단하고 훌륭한 작품입니다. 저에게 많은 시간을 절약했습니다.
Chris Hough

1

세 번째 옵션은 모든 미래 지향적 애플리케이션에 가장 적합합니다. 개인 레코드에 더 많은 필드를 추가하고 싶을 것이므로 첫 번째 옵션은 적합하지 않습니다. 또한 저장해야 할 사람이 많을 가능성이 매우 높고 레코드를 빠르게 조회하기를 원할 것입니다. 따라서 옵션 # 2 에서처럼 간단한 배열로 덤프하는 것도 좋은 생각이 아닙니다.

세 번째 패턴은 임의의 문자열을 ID로 사용하고 복잡한 Person 구조를 가지며 일정한 시간에 개인 레코드를 가져오고 설정할 수있는 옵션을 제공합니다. 확실히 갈 길입니다.

옵션 # 3에없는 한 가지는 안정적인 결정 론적 순서입니다 (옵션 # 2의 장점). 이것이 필요한 경우, 순서대로 사람을 나열해야 할 때를 위해 별도의 구조로 정렬 된 사람 ID 배열을 유지하는 것이 좋습니다. 장점은 동일한 데이터 세트의 다른 순서에 대해 여러 배열을 유지할 수 있다는 것입니다.


0

값으로 이름 만 가질 수 있다는 제약이 주어지면 첫 번째 옵션을 선택합니다. 가장 깨끗하고 오버 헤드가 적고 조회가 가장 빠릅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.