JavaScript에서 세트를 모방합니까?
JavaScript로 일하고 있습니다. 다음 속성을 사용하여 정렬되지 않은 고유 한 문자열 값 목록을 저장하고 싶습니다 .
- '목록에 A'가 있는지 묻는 가장 빠른 방법은 무엇입니까?
- '목록에 A가 있으면 목록에서 A를 삭제'하는 빠른 방법
- '목록에 A를 아직 추가하지 않은 경우 추가'하는 빠른 방법.
내가 정말로 원하는 것은 세트입니다. JavaScript에서 세트를 모방하는 가장 좋은 방법에 대한 제안 사항이 있습니까?
이 질문은 속성을 저장하는 키와 값이 모두 true로 설정된 Object를 사용하는 것이 좋습니다 . 합리적인 방법입니까?
ES6 가능 환경 (예 : node.js, 필요한 ES6 기능이있는 특정 브라우저 또는 환경에 대한 ES6 코드를 변환하는 특정 브라우저)에서 프로그래밍하는 경우 ES6에 Set
내장 된 객체를 사용할 수 있습니다 . 그것은 매우 좋은 기능을 가지고 있으며 귀하의 환경에서 그대로 사용할 수 있습니다.
ES5 환경의 많은 간단한 것들에 대해 Object를 사용하면 매우 효과적입니다. 경우 obj
개체이며, A
당신이 세트에 조작하려는 값을 갖는 변수이다, 당신은이 작업을 수행 할 수 있습니다 :
초기화 코드 :
// create empty object
var obj = {};
// or create an object with some items already in it
var obj = {"1":true, "2":true, "3":true, "9":true};
질문 1 : 가 A
목록에 :
if (A in obj) {
// put code here
}
질문 2 : 목록에 'A'가 있으면 삭제하십시오.
delete obj[A];
질문 3 : 목록에 'A'가 없으면 목록에 추가하십시오
obj[A] = true;
완전성 A
을 위해 목록 에 있는지 여부에 대한 테스트 는 다음과 같이 조금 더 안전합니다.
if (Object.prototype.hasOwnProperty.call(obj, A))
// put code here
}
기본 객체의 내장 메소드 및 / 또는 속성과 속성이 충돌 할 가능성이 있기 때문입니다 constructor
.
ES6의 사이드 바 : ECMAScript 6 의 현재 작업 버전 또는 ES 2015라는 것은 Set 객체 가 내장되어 있습니다. 현재 일부 브라우저에서 구현되었습니다. 브라우저 가용성이 시간이 지남에 따라 변화하기 때문에 들어 줄에서 볼 수 Set
있는 이 ES6 호환성 테이블 브라우저 가용성의 현재 상태를 볼 수 있습니다.
내장 Set 객체의 한 가지 장점은 Object와 같이 모든 키를 문자열로 강제 변환하지 않으므로 별도의 키로 5와 "5"를 모두 가질 수 있다는 것입니다. 또한 문자열 변환없이 세트에서 직접 객체를 사용할 수도 있습니다. 다음 은 Set 개체에 대한 일부 기능 및 MDN 설명서 를 설명 하는 기사 입니다 .
이제 ES6 세트 객체에 대한 폴리 필을 작성하여 지금 사용할 수 있으며 브라우저가 지원하는 경우 내장 세트 객체를 자동으로 연기합니다. 이것은 ES7 호환 코드를 작성하여 IE7까지 계속 작동한다는 이점이 있습니다. 그러나 몇 가지 단점이 있습니다. ES6 세트 인터페이스는 ES6 이터레이터를 활용하므로 원하는 작업을 수행 할 수 for (item of mySet)
있으며 세트를 통해 자동으로 반복됩니다. 그러나 이러한 유형의 언어 기능은 polyfill을 통해 구현할 수 없습니다. 새로운 ES6 언어 기능을 사용하지 않고 ES6 세트를 계속 반복 할 수 있지만 솔직히 새로운 언어 기능이 없으면 아래에 포함 된 다른 세트 인터페이스만큼 편리하지 않습니다.
둘 다보고 나에게 가장 적합한 것을 결정할 수 있습니다. ES6 세트 폴리 필은 https://github.com/jfriend00/ES6-Set에 있습니다.
참고로, 자체 테스트에서 Firefox v29 Set 구현이 현재 사양의 초안에서 완전히 최신 상태가 아님을 알았습니다. 예를 들어 .add()
사양 설명 및 내 polyfill 지원과 같은 메소드 호출 을 연결할 수 없습니다 . 이것은 아직 확정되지 않았기 때문에 동작 사양의 문제 일 수 있습니다.
사전 빌드 세트 오브젝트 : 모든 브라우저에서 사용할 수있는 세트에서 조작하기위한 메소드가있는 이미 빌드 된 오브젝트를 원하는 경우 다른 유형의 세트를 구현하는 일련의 다른 사전 빌드 된 오브젝트를 사용할 수 있습니다. set 객체의 기본을 구현하는 작은 코드 인 miniSet이 있습니다. 또한 더 많은 기능이 풍부한 세트 객체와 사전 (각 키의 값을 저장 / 검색 할 수 있음) 및 객체 세트 (JS 객체 또는 DOM 객체를 제공하는 DOM 객체)를 포함하여 여러 파생물이 있습니다. 각각 고유의 키를 생성하는 함수 또는 ObjectSet가 키를 생성합니다).
다음은 miniSet 코드의 사본입니다 (가장 최신 코드는 github에 있습니다 ).
"use strict";
//-------------------------------------------
// Simple implementation of a Set in javascript
//
// Supports any element type that can uniquely be identified
// with its string conversion (e.g. toString() operator).
// This includes strings, numbers, dates, etc...
// It does not include objects or arrays though
// one could implement a toString() operator
// on an object that would uniquely identify
// the object.
//
// Uses a javascript object to hold the Set
//
// This is a subset of the Set object designed to be smaller and faster, but
// not as extensible. This implementation should not be mixed with the Set object
// as in don't pass a miniSet to a Set constructor or vice versa. Both can exist and be
// used separately in the same project, though if you want the features of the other
// sets, then you should probably just include them and not include miniSet as it's
// really designed for someone who just wants the smallest amount of code to get
// a Set interface.
//
// s.add(key) // adds a key to the Set (if it doesn't already exist)
// s.add(key1, key2, key3) // adds multiple keys
// s.add([key1, key2, key3]) // adds multiple keys
// s.add(otherSet) // adds another Set to this Set
// s.add(arrayLikeObject) // adds anything that a subclass returns true on _isPseudoArray()
// s.remove(key) // removes a key from the Set
// s.remove(["a", "b"]); // removes all keys in the passed in array
// s.remove("a", "b", ["first", "second"]); // removes all keys specified
// s.has(key) // returns true/false if key exists in the Set
// s.isEmpty() // returns true/false for whether Set is empty
// s.keys() // returns an array of keys in the Set
// s.clear() // clears all data from the Set
// s.each(fn) // iterate over all items in the Set (return this for method chaining)
//
// All methods return the object for use in chaining except when the point
// of the method is to return a specific value (such as .keys() or .isEmpty())
//-------------------------------------------
// polyfill for Array.isArray
if(!Array.isArray) {
Array.isArray = function (vArg) {
return Object.prototype.toString.call(vArg) === "[object Array]";
};
}
function MiniSet(initialData) {
// Usage:
// new MiniSet()
// new MiniSet(1,2,3,4,5)
// new MiniSet(["1", "2", "3", "4", "5"])
// new MiniSet(otherSet)
// new MiniSet(otherSet1, otherSet2, ...)
this.data = {};
this.add.apply(this, arguments);
}
MiniSet.prototype = {
// usage:
// add(key)
// add([key1, key2, key3])
// add(otherSet)
// add(key1, [key2, key3, key4], otherSet)
// add supports the EXACT same arguments as the constructor
add: function() {
var key;
for (var i = 0; i < arguments.length; i++) {
key = arguments[i];
if (Array.isArray(key)) {
for (var j = 0; j < key.length; j++) {
this.data[key[j]] = key[j];
}
} else if (key instanceof MiniSet) {
var self = this;
key.each(function(val, key) {
self.data[key] = val;
});
} else {
// just a key, so add it
this.data[key] = key;
}
}
return this;
},
// private: to remove a single item
// does not have all the argument flexibility that remove does
_removeItem: function(key) {
delete this.data[key];
},
// usage:
// remove(key)
// remove(key1, key2, key3)
// remove([key1, key2, key3])
remove: function(key) {
// can be one or more args
// each arg can be a string key or an array of string keys
var item;
for (var j = 0; j < arguments.length; j++) {
item = arguments[j];
if (Array.isArray(item)) {
// must be an array of keys
for (var i = 0; i < item.length; i++) {
this._removeItem(item[i]);
}
} else {
this._removeItem(item);
}
}
return this;
},
// returns true/false on whether the key exists
has: function(key) {
return Object.prototype.hasOwnProperty.call(this.data, key);
},
// tells you if the Set is empty or not
isEmpty: function() {
for (var key in this.data) {
if (this.has(key)) {
return false;
}
}
return true;
},
// returns an array of all keys in the Set
// returns the original key (not the string converted form)
keys: function() {
var results = [];
this.each(function(data) {
results.push(data);
});
return results;
},
// clears the Set
clear: function() {
this.data = {};
return this;
},
// iterate over all elements in the Set until callback returns false
// myCallback(key) is the callback form
// If the callback returns false, then the iteration is stopped
// returns the Set to allow method chaining
each: function(fn) {
this.eachReturn(fn);
return this;
},
// iterate all elements until callback returns false
// myCallback(key) is the callback form
// returns false if iteration was stopped
// returns true if iteration completed
eachReturn: function(fn) {
for (var key in this.data) {
if (this.has(key)) {
if (fn.call(this, this.data[key], key) === false) {
return false;
}
}
}
return true;
}
};
MiniSet.prototype.constructor = MiniSet;
당신은 같은 속성없이 객체를 만들 수 있습니다
var set = Object.create(null)
이것은 세트 역할을 할 수 있고 사용할 필요가 없습니다 hasOwnProperty
.
var set = Object.create(null); // create an object with no properties
if (A in set) { // 1. is A in the list
// some code
}
delete set[a]; // 2. delete A from the list if it exists in the list
set[A] = true; // 3. add A to the list if it is not already present
ECMAScript 6부터 Set 데이터 구조는 기본 제공 기능 입니다. node.js 버전과의 호환성은 여기 에서 찾을 수 있습니다 .
자바 스크립트의 ES6 버전에서는, 형태에 구축 세트 ( 브라우저와 체크 호환성 ).
var numbers = new Set([1, 2, 4]); // Set {1, 2, 4}
집합에 요소 를 추가 하려면 간단히을 사용 합니다.이 요소는 .add()
실행되어 O(1)
설정에 요소를 추가하거나 (존재하지 않는 경우) 이미 존재하는 경우 아무 것도 수행하지 않습니다. 거기에 모든 유형의 요소를 추가 할 수 있습니다 (배열, 문자열, 숫자)
numbers.add(4); // Set {1, 2, 4}
numbers.add(6); // Set {1, 2, 4, 6}
집합 의 요소 수 를 확인 하려면을 사용하면됩니다 .size
. 또한 실행O(1)
numbers.size; // 4
세트에서 요소 를 제거 하려면을 사용하십시오 .delete()
. 값이 있고 제거 된 경우 true를 반환하고 값이 없으면 false를 반환합니다. 에서 실행됩니다 O(1)
.
numbers.delete(2); // true
numbers.delete(2); // false
요소가 세트에 있는지 여부 를 확인 하려면 요소가 세트에 .has()
있으면 true를, 그렇지 않으면 false를 리턴합니다. 에서 실행됩니다 O(1)
.
numbers.has(3); // false
numbers.has(1); // true
원하는 방법 외에도 몇 가지 추가 방법이 있습니다.
numbers.clear();
세트에서 모든 요소를 제거합니다.numbers.forEach(callback);
삽입 순서로 세트의 값을 반복numbers.entries();
모든 값의 반복자를 생성numbers.keys();
세트와 동일한 키를 돌려줍니다numbers.values()
객체 유형 값만 추가 할 수있는 약점도 있습니다.
현재 숫자와 문자열에서 잘 작동하는 Sets 구현을 시작했습니다. 나의 주된 초점은 차이 연산에 있었고, 나는 그것을 가능한 한 효율적으로 만들려고 노력했다. 포크와 코드 리뷰는 환영합니다!
https://github.com/mcrisc/SetJS
방금 d3.js 라이브러리에 세트, 맵 및 기타 데이터 구조가 구현되어 있음을 알았습니다. 나는 그들의 효율성에 대해 논쟁 할 수 없지만 그것이 인기있는 도서관이라는 사실로 판단하면 그것이 필요한 것이어야합니다.
설명서는 여기
편의상 링크에서 복사합니다 (처음 3 가지 기능이 관심 대상입니다)
- d3.set ([배열])
새로운 세트를 구축합니다. array가 지정되면 주어진 문자열 값의 배열을 리턴 된 세트에 추가합니다.
- set.has (값)
이 세트에 지정된 값 캐릭터 라인의 엔트리가있는 경우 만 true를 리턴합니다.
- set.add (값)
지정된 값 문자열을이 세트에 추가합니다.
- set.remove (값)
세트에 지정된 값 문자열이 포함 된 경우이를 제거하고 true를 리턴합니다. 그렇지 않으면이 메소드는 아무 것도 수행하지 않고 false를 리턴합니다.
- set.values ()
이 세트의 캐릭터 라인 치의 배열을 돌려줍니다. 반환 된 값의 순서는 임의적입니다. 문자열 집합의 고유 한 값을 계산하는 편리한 방법으로 사용할 수 있습니다. 예를 들면 다음과 같습니다.
d3.set ([ "foo", "bar", "foo", "baz"]). values (); // "foo", "bar", "baz"
- set.forEach (기능)
이 세트의 각 값에 대해 지정된 함수를 호출하여 값을 인수로 전달합니다. 이 기능의 컨텍스트는이 세트입니다. 미정 도리를 돌려줍니다. 반복 순서는 임의적입니다.
- set.empty ()
이 세트에 제로의 값이있는 경우에 한정해 true를 리턴합니다.
- set.size ()
이 세트의 값의 수를 돌려줍니다.
그렇습니다. 이는 합리적인 방법입니다. 모든 것이 (이 경우에는 잘 사용됩니다) 직접 액세스 할 수있는 많은 키 / 값입니다.
추가하기 전에 이미 존재하는지 확인하거나 존재를 표시해야하는 경우 다시 "추가"하면 실제로 아무것도 변경되지 않으며 개체에 다시 설정됩니다.
참고 URL : https://stackoverflow.com/questions/7958292/mimicking-sets-in-javascript
'Programing' 카테고리의 다른 글
d3.js 시각화 레이아웃을 반응 형으로 만드는 가장 좋은 방법은 무엇입니까? (0) | 2020.04.26 |
---|---|
Java 특성 파일을 사용하는 방법은 무엇입니까? (0) | 2020.04.26 |
Google에 가입 한 경우 Bitbucket git 자격 증명 (0) | 2020.04.26 |
Ruby에서 DateTime과 시간의 차이 (0) | 2020.04.26 |
Oracle의 이중 테이블은 무엇입니까? (0) | 2020.04.26 |