Javascript로 목록 이해하기
Javascript가 Python의 목록 이해 와 같은 작업을 수행하도록하는 가장 깨끗한 방법은 무엇입니까 ?
파이썬에서 이름이 '뽑아 내고 싶은'객체 목록이 있으면 이렇게 할 것입니다.
list_of_names = [x.name for x in list_of_objects]
자바 스크립트에서 나는 for 루프 구조를 사용하는 것 외에 더 '아름다운'방법을 실제로 보지 못합니다.
참고 : 저는 jQuery를 사용하고 있습니다. 아마도 이것을 가능하게 만드는 멋진 기능이 있습니까?
보다 구체적으로, $('input')
모든 input
요소 를 가져 오기 위해 jQuery 선택기를 사용한다고 가정 해 보겠습니다. 이러한 각 요소 (즉, 배열의 모든 문자열)에 대한 모든 특성 의 배열을 가장 깔끔하게 만드는 방법은 무엇입니까?name
input
$('input').attr('name')
Array.map을 사용하는 일반적인 경우 에는 자바 스크립트 1.6 (즉, IE <9를 제외한 모든 브라우저에서 작동)이 필요 하거나 MooTools와 같은 객체 증강 프레임 워크가 모든 브라우저에서 작동합니다.
var list_of_names = document.getElementsByTagName('input').map(
function(element) { return element.getAttribute('name'); }
);
jQuery 특정 예제는 모든 브라우저에서 작동합니다.
var list_of_names = jQuery.map(jQuery('input'), function(element) { return jQuery(element).attr('name'); });
사용하는 다른 답변 .each
이 잘못되었습니다. 코드 자체는 아니지만 구현은 차선책입니다.
편집 : Javascript 1.7에 도입 된 배열 이해 도 있지만 이것은 순전히 구문에 의존하며 기본적으로 부족한 브라우저에서 에뮬레이션 할 수 없습니다. 이것은 당신이 게시 한 파이썬 스 니펫에 자바 스크립트에서 얻을 수있는 가장 가까운 것입니다.
목록 이해에는 몇 가지 부분이 있습니다.
- 무언가 선택하기
- 무언가의 집합에서
- 무언가로 필터링 됨
JavaScript에서는 ES5 (IE9 +, Chrome 및 FF에서 지원한다고 생각합니다)부터 배열 에서 map
및 filter
함수를 사용할 수 있습니다 .
맵 및 필터를 사용하여이를 수행 할 수 있습니다.
var list = [1,2,3,4,5].filter(function(x){ return x < 4; })
.map(function(x) { return 'foo ' + x; });
console.log(list); //["foo 1", "foo 2", "foo 3"]
이는 추가 메서드를 설정하거나 다른 프레임 워크를 사용하지 않고도 얻을 수있는 것만 큼 좋습니다.
구체적인 질문은 ...
jQuery 사용 :
$('input').map(function(i, x) { return x.name; });
jQuery없이 :
var inputs = [].slice.call(document.getElementsByTagName('input'), 0),
names = inputs.map(function(x) { return x.name; });
[].slice.call()
(가) 변환 그냥 NodeList
에 Array
.
"아름다운"자바 스크립트에 관심이있는 사람들은 자바 스크립트 로 컴파일되는 언어 인 CoffeeScript를 확인해야 할 것입니다 . Javascript에는 목록 이해와 같은 것이 없기 때문에 본질적으로 존재합니다.
특히 Coffeescript의 목록 이해력은 Python보다 훨씬 유연합니다. 여기 에서 목록 이해 문서를 참조 하십시오 .
예를 들어이 코드는 요소 의 name
속성 배열을 생성 합니다 input
.
[$(inp).attr('name') for inp in $('input')]
그러나 잠재적 인 단점은 결과 Javascript가 장황하고 IMHO가 혼란 스럽다는 것입니다.
var inp;
[
(function() {
var _i, _len, _ref, _results;
_ref = $('input');
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
inp = _ref[_i];
_results.push($(inp).attr('name'));
}
return _results;
})()
];
따라서 파이썬의 목록 이해는 실제로 매핑과 필터링이라는 두 가지 작업을 한 번에 수행합니다. 예를 들면 :
list_of_names = [x.name for x in list_of_object if x.enabled]
예제에서 볼 수 있듯이 매핑 부분 만 원하는 경우 jQuery의지도 기능을 사용할 수 있습니다. 필터링이 필요한 경우 jQuery의 "grep"기능을 사용할 수 있습니다.
재사용 가능한 방법은 다음과 같은 작은 jQuery 플러그인을 만드는 것입니다.
jQuery.fn.getArrayOfNames = function() {
var arr = [];
this.each( function() { arr.push(this.name || ''); } );
return arr;
};
그런 다음 다음과 같이 사용할 수 있습니다.
var list_of_names = $('input').getArrayOfNames();
목록 이해력은 아니지만 자바 스크립트에는 존재하지 않습니다. 당신이 할 수있는 일은 자바 스크립트와 jquery를 사용하는 것뿐입니다.
배열 이해는 ECMAScript 6 초안의 일부입니다. 현재 (2014 년 1 월) Mozilla / Firefox의 JavaScript 만이를 구현합니다.
var numbers = [1,2,3,4];
var squares = [i*i for (i of numbers)]; // => [1,4,9,16]
var somesquares = [i*i for (i of numbers) if (i > 2)]; // => [9,16]
ECMAScript 6은 최근 C # 및 F #과 유사한 왼쪽에서 오른쪽 구문으로 전환되었지만 :
var squares = [for (i of numbers) i*i]; // => [1,4,9,16]
http://kangax.github.io/es5-compat-table/es6/#Array_comprehensions
예 — 목록 이해도 그리워요.
다음은 @gonchuki의 대답보다 약간 덜 장황한 대답이며 객체 유형 대신 실제 배열로 변환합니다.
var list_of_names = $('input').map(function() {
return $(this).attr('name');
}).toArray();
이것의 사용 사례는 선택된 모든 체크 박스를 가져 와서 URL의 해시에 결합하는 것입니다.
window.location.hash = $('input:checked').map(function() {
return $(this).attr('id');
}).toArray().join(',');
한 줄 접근 방식이 있으며, 목록 생성자에서 중첩 된 폐쇄 함수를 사용합니다. 그리고 시퀀스를 생성하는 데 오래 걸리는 함수입니다. 아래에 정의되어 있습니다.
var __ = generate = function(initial, max, list, comparision) {
if (comparision(initial))
list.push(initial);
return (initial += 1) == max + 1 ? list : __(initial, max, list, comparision);
};
[(function(l){ return l; })(__(0, 30, [], function(x) { return x > 10; }))];
// returns Array[20]
var val = 16;
[(function(l){ return l; })(__(0, 30, [], function(x) { return x % val == 4; }))];
// returns Array[2]
이것은 Python의 range (min, max)와 같은 범위 기반 구현입니다. 또한 목록 이해는 다음 형식을 따릅니다.
[{closure function}({generator function})];
일부 테스트 :
var alist = [(function(l){ return l; })(__(0, 30, [], function(x) { return x > 10; }))];
var alist2 = [(function(l){ return l; })(__(0, 1000, [], function(x) { return x > 10; }))];
// returns Array[990]
var alist3 = [(function(l){ return l; })(__(40, 1000, [], function(x) { return x > 10; }))];
var threshold = 30*2;
var alist3 = [(function(l){ return l; })(__(0, 65, [], function(x) { return x > threshold; }))];
// returns Array[5]
이 솔루션이 가장 깨끗하지는 않지만 작업이 완료됩니다. 그리고 프로덕션에서 나는 아마 그것에 대해 조언 할 것입니다.
마지막으로 내 "생성"방법에 대해 재귀를 사용하지 않도록 선택할 수 있습니다. 또는 많은 인기있는 Javascript 라이브러리의 내장 함수를 사용하는 것이 더 좋습니다. 다음은 개체 속성을 수용하는 오버로드 된 구현입니다.
// A list generator overload implementation for
// objects and ranges based on the arity of the function.
// For example [(function(l){ return l; })(__(0, 30, [], function(x) { return x > 10; }))]
// will use the first implementation, while
// [(function(l){ return l; })(__(objects, 'name', [], function(x, y) { var x = x || {}; return x[y] }))];
// will use the second.
var __ = generator = function(options) {
return arguments.length == 4 ?
// A range based implemention, modeled after pythons range(0, 100)
(function (initial, max, list, comparision) {
var initial = arguments[0], max = arguments[1], list = arguments[2], comparision = arguments[3];
if (comparision(initial))
list.push(initial);
return (initial += 1) == max + 1 ? list : __(initial, max, list, comparision);
})(arguments[0], arguments[1], arguments[2], arguments[3]):
// An object based based implementation.
(function (object, key, list, check, acc) {
var object = arguments[0], key = arguments[1], list = arguments[2], check = arguments[3], acc = arguments[4];
acc = acc || 0;
if (check(object[acc], key))
list.push(object[acc][key]);
return (acc += 1) == list.length + 1 ? list : __(object, key, list, check, acc);
})(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
};
용법:
var threshold = 10;
[(function(l){ return l; })(__(0, 65, [], function(x) { return x > threshold; }))];
// returns Array[5] -> 60, 61, 62, 63, 64, 65
var objects = [{'name': 'joe'}, {'name': 'jack'}];
[(function(l){ return l; })(__(objects, 'name', [], function(x, y) { var x = x || {}; return x[y] }))];
// returns Array[1] -> ['Joe', 'Jack']
[(function(l){ return l; })(__(0, 300, [], function(x) { return x > 10; }))];
내가 아는 구문은 짜증나!
행운을 빕니다.
이것은 Coffeescript가 정말로 빛나는 곳의 예입니다.
pows = [x**2 for x in foo_arr]
list_of_names = [x.name for x in list_of_objects]
동등한 Javascript는 다음과 같습니다.
var list_of_names, pows, x;
pows = [
(function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = foo_arr.length; _i < _len; _i++) {
x = foo_arr[_i];
_results.push(Math.pow(x, 2));
}
return _results;
})()
];
list_of_names = [
(function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = list_of_objects.length; _i < _len; _i++) {
x = list_of_objects[_i];
_results.push(x.name);
}
return _results;
})()
];
Using jQuery .each()
function, you can loop through each element, get the index of the current element and using that index, you can add the name attribute to the list_of_names
array...
var list_of_names = new Array();
$('input').each(function(index){
list_of_names[index] = $(this).attr('name');
});
While this is essentially a looping method, which you specified you did not want, it is an incredibly neat implementation of looping and allows you to run the loop on specific selectors.
Hope that helps :)
ReferenceURL : https://stackoverflow.com/questions/4964456/make-javascript-do-list-comprehension
'Development Tip' 카테고리의 다른 글
자동 완성 콤보 박스를 만드는 방법은 무엇입니까? (0) | 2020.12.26 |
---|---|
java.util.AbstractList.add의 UnsupportedOperationException (0) | 2020.12.26 |
.NET에서 비 차단, 단일 스레드, 비동기 웹 서버 (예 : Node.js)가 가능합니까? (0) | 2020.12.25 |
Flask 앱의 공통 폴더 / 파일 구조 (0) | 2020.12.25 |
iOS 7의 기본 공유 (0) | 2020.12.25 |