Javascript에서 배열 키를 얻는 방법은 무엇입니까?


80

이 코드로 만든 배열이 있습니다.

var widthRange = new Array();
widthRange[46] = { min:0,  max:52 };
widthRange[66] = { min:52, max:70 };
widthRange[90] = { min:70, max:94 };

루프에서 각 값 46, 66, 90을 가져오고 싶습니다. 나는 시도 for (var key in widthRange)했지만 이것은 나에게 많은 추가 속성을 제공합니다 (객체에 대한 기능이라고 가정합니다). 값이 순차적이지 않기 때문에 일반 for 루프를 사용할 수 없습니다.


9
숫자 키가 있지만 실제로는 배열 데이터가 아닌 데이터가있는 것 같습니다. 여기서 일반 객체를 사용하는 방법을 살펴 보겠습니다.
Quentin

@Quentin 희소 배열이라고합니다. 성능 측면에서는 여기에서 객체 대신 배열을 사용하는 것이 가장 좋습니다. 또한 성능 측면에서 가장 좋은 답변은 나열되지 않았습니다 Array.prototype.forEach. Object.keys어레이 호출 은 브라우저가 최적화하지 않기 때문에 성능이 떨어집니다. for(var key in array)프로토 타입을 탐색하고 만나는 각 숫자 키를 문자열 화하기 때문에 좋지 않습니다 (배수를 base10으로 변환하는 것은 매우 느립니다). forEach그러나, 스파 스 배열을 반복 할 목적으로 정확하게 설계된 다른 솔루션에 비해 코드 우수한 성능을 제공합니다
잭 Giffin

답변:


96

다음과 hasOwnProperty같이 속성이 객체 자체에 실제로 정의되어 있는지 확인 하려면 함수 를 호출해야합니다 .

for (var key in widthRange) {
    if (key === 'length' || !widthRange.hasOwnProperty(key)) continue;
    var value = widthRange[key];
}

에 대한 별도의 확인이 필요합니다 length.
그러나 여기에서 배열을 사용해서는 안됩니다. 일반 객체를 사용해야합니다. 모든 Javascript 객체는 연관 배열로 작동합니다.

예를 들면 :

var widthRange = { };  //Or new Object()
widthRange[46] = { sel:46, min:0,  max:52 };
widthRange[66] = { sel:66, min:52, max:70 };
widthRange[90] = { sel:90, min:70, max:94 };

2
정말? 와우 나는 여기서 매일 무언가를 배우고, 너무 자주 당신에게서 온 것입니다. SLaks :-) Array가 명시 적으로 설정된 인덱스를 추적하는 것에 놀랐습니다. 나는 안 될지도 몰라.
Pointy

@SLaks : 감사합니다. 객체로 변경하는 것이 가장 좋은 해결책 인 것 같습니다. 한 가지 더 질문 : 역순으로 반복하는 방법이 있습니까?
DisgruntledGoat

아니; 직접해야합니다.
SLaks

2
별도의 수표가 필요한 이유는 무엇 length입니까? [[DontEnum]]모든 브라우저에서 로 표시되지 않습니까?
Roatin Marth

@Roatin : 모르겠어요. 죄송합니다보다 더 안전.
SLaks


18

어떤 종류의 배열 / 컬렉션 조작 또는 검사를 수행하는 경우 Underscore.js 사용하는 것이 좋습니다 . 작고 잘 테스트되었으며 몇 일 / 주 / 년의 자바 스크립트 두통을 줄일 수 있습니다. 키 기능은 다음과 같습니다.

개체 속성의 모든 이름을 검색합니다.

_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]

4

당신의 배열이 arr = [ { a: 1, b: 2, c: 3 }, { a: 4, b: 5, c: 6 }, { a: 7, b: 8, c: 9 } ]당신이 할 수있는 것처럼 보인다고 말하세요.

arr.map((o) => {
    return Object.keys(o)
}).reduce((prev, curr) => {
    return prev.concat(curr)
}).filter((col, i, array) => {
    return array.indexOf(col) === i
});

["a", "b", "c"]


3
for (var i = 0; i < widthRange.length; ++i) {
  if (widthRange[i] != null) {
    // do something
  }
}

배열이 작동하는 방식이 아니기 때문에 설정 한 키만 얻을 수는 없습니다. 요소 46을 설정하면 0에서 45까지도 설정됩니다 (널 임에도 불구하고).

항상 두 개의 배열을 가질 수 있습니다.

var widthRange = [], widths = [], newVal = function(n) {
  widths.push(n);
  return n;
};
widthRange[newVal(26)] = { whatever: "hello there" };

for (var i = 0; i < widths.length; ++i) {
  doSomething(widthRange[widths[i]]);
}

편집 하십시오 내가 여기에 모두 젖었을 수도 있습니다 ...


배열은 길이 만 추적하고 통과하지 않고 많은 객체를 생성합니다. 기본적으로 새 인덱스가 발견되면 새 인덱스가 길이보다 큰지 확인합니다. 새 인덱스가 새 길이가되는 경우. 때문에 당신이-에 대한 루프로 정의에만 인덱스를 얻을 수 있음을의


1

귀하의 원래 예제는 저에게 잘 작동합니다.

<html>
<head>
</head>
<body>
<script>
var widthRange = new Array();
widthRange[46] = { sel:46, min:0,  max:52 };
widthRange[66] = { sel:66, min:52, max:70 };
widthRange[90] = { sel:90, min:70, max:94 };

var i = 1;
for (var key in widthRange)
{
    document.write("Key #" + i + " = " + key + "; &nbsp;&nbsp;&nbsp; min/max = " + widthRange[key].min + "/" + widthRange[key].max + "<br />");
    i++;
}
</script>
</html>

브라우저 결과 (Windows XP의 Firefox 3.6.2) :

Key #1 = 46;     min/max = 0/52
Key #2 = 66;     min/max = 52/70
Key #3 = 90;     min/max = 70/94

2
나는 그가 Prototype이나 비슷한 것을 가져오고 있다고 확신합니다. 일반적으로 이러한 "in"루프는 위험합니다.
Pointy

글쎄, 나는 jQuery를 사용하고 있지만 mootools를 사용하는 Joomla도 그 속성을 추가하고 있습니다.
DisgruntledGoat

1

나는 당신 이 이것을 위해 {}배열 ( [])이 아닌 Object ( ) 를 사용해야한다고 생각합니다 .

데이터 세트는 각 키와 연관됩니다. 물건을 사용하면 비명을 지른다. 하다:

var obj = {};
obj[46] = { sel:46, min:0,  max:52 };
obj[666] = { whatever:true };

// This is what for..in is for
for (var prop in obj) {
  console.log(obj[prop]);
}

다음과 같은 유틸리티가 도움이 될 수 있습니다.

window.WidthRange = (function () {
  var obj = {};
  return {
    getObj: function () {return obj;}
    , add: function (key, data) {
        obj[key] = data;
        return this; // enabling chaining
      }
  }
})();

// Usage (using chaining calls):
WidthRange.add(66, {foo: true})
.add(67, {bar: false})
.add(69, {baz: 'maybe', bork:'absolutely'});

var obj = WidthRange.getObj();
for (var prop in obj) {
  console.log(obj[prop]);
}

0

작동하는 것 같습니다.

var widthRange = new Array();
widthRange[46] = { sel:46, min:0,  max:52 };
widthRange[66] = { sel:66, min:52, max:70 };
widthRange[90] = { sel:90, min:70, max:94 };

for (var key in widthRange)
{
    document.write(widthRange[key].sel + "<br />");
    document.write(widthRange[key].min + "<br />");
    document.write(widthRange[key].max + "<br />");
}

0

나는 모든 객체 인스턴스에서 잘 작동하는 함수를 작성했습니다 (배열은 그 것입니다).

Object.prototype.toArray = function()
{
    if(!this)
    {
      return null;
    }

    var c = [];

    for (var key in this) 
    {
        if ( ( this instanceof Array && this.constructor === Array && key === 'length' ) || !this.hasOwnProperty(key) ) 
        {
            continue;
        }

        c.push(this[key]);
    }

    return c;
};

용법:

var a   = [ 1, 2, 3 ];
a[11]   = 4;
a["js"] = 5;

console.log(a.toArray());

var b = { one: 1, two: 2, three: 3, f: function() { return 4; }, five: 5 };
b[7] = 7;

console.log(b.toArray());

산출:

> [ 1, 2, 3, 4, 5 ]
> [ 7, 1, 2, 3, function () { return 4; }, 5 ]

누구에게나 유용 할 수 있습니다.


2
제작하지 않은 프로토 타입을 확장하는 것은 얼마나 편리하다고 생각하든 매우 나쁜 생각입니다.
doug65536

0

... ????

또는 사용하려는 항목 목록이있는 경우 ...

var range = [46, 66, 90]
    , widthRange=[]
    , write=[];

    widthRange[46] = { min:0, max:52 }; 
    widthRange[66] = { min:52, max:70 }; 
    widthRange[90] = { min:70, max:94 }; 

for(var x=0; x<range.length; x++){var key, wr;

    key = range[x];

    wr = widthRange[key] || false;

    if(wr===false){continue;}

    write.push(['key: #',key, ', min: ', wr.min, 'max:', wr.max].join(''));

    }

0

입력 데이터 :

let widthRange = new Array()
widthRange[46] = { min:0,  max:52 }
widthRange[61] = { min:52, max:70 }
widthRange[62] = { min:52, max:70 }
widthRange[63] = { min:52, max:70 }
widthRange[66] = { min:52, max:70 }
widthRange[90] = { min:70, max:94 }

선언적 접근 방식 :

const relevantKeys = [46,66,90]
const relevantValues = Object.keys(widthRange)
    .filter(index => relevantKeys.includes(parseInt(index)))
    .map(relevantIndex => widthRange[relevantIndex])

Object.keys키를 가져 parseInt오고 숫자로 캐스팅하는 데 사용합니다. filter원하는 것을 얻으려면. map당신이 추구하는 인덱스의 원래 객체에서 배열을 만들려면Object.keys는 객체 값을 잃기 만듭니다.

디버그 :

console.log(widthRange)
console.log(relevantKeys)
console.log(relevantValues)

0

질문은 꽤 오래되었지만 요즘에는 효율적이고 키를 숫자로 유지하는 forEach를 사용할 수 있습니다.

let keys = widthRange.map((v,k) => k).filter(i=>i!==undefined))

이것은 widthRange를 반복하고 키 값으로 새 배열을 만든 다음 정의 된 값만 가져 와서 모든 희소 슬롯을 필터링합니다.

(나쁜 생각이지만 철저하게 : 슬롯 0이 항상 비어 있었다면 filter(i=>i)또는filter(Boolean)

그리고 덜 효율적일 수 있지만 숫자는 let keys = Object.keys(array).map(i=>i*1)

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