각 요소에 대해 호출 된 함수가 true
또는을 반환하는지 여부에 따라 두 개로 분할하려는 Javascript 배열이 false
있습니다. 기본적으로 이것은이다 array.filter
, 그러나 나는 또한 손에 필터링 된 요소를 가지고 싶습니다 아웃 .
현재 내 계획은 array.forEach
각 요소에 대해 조건 자 함수 를 사용 하고 호출하는 것입니다. 이것이 참인지 거짓인지에 따라 현재 요소를 두 개의 새로운 배열 중 하나에 푸시합니다. 더 우아하거나 더 나은 방법이 있습니까? 예 를 들어 array.filter
는 반환하기 전에 요소를 다른 배열로 푸시합니다 false
.
답변
ES6를 사용하면 reduce로 스프레드 구문을 사용할 수 있습니다.
function partition(array, isValid) {
return array.reduce(([pass, fail], elem) => {
return isValid(elem) ? [[...pass, elem], fail] : [pass, [...fail, elem]];
}, [[], []]);
}
const [pass, fail] = partition(myArray, (e) => e > 5);
또는 한 줄로 :
const [pass, fail] = a.reduce(([p, f], e) => (e > 5 ? [[...p, e], f] : [p, [...f, e]]), [[], []]);
답변
lodash.partition 을 사용할 수 있습니다.
var users = [
{ 'user': 'barney', 'age': 36, 'active': false },
{ 'user': 'fred', 'age': 40, 'active': true },
{ 'user': 'pebbles', 'age': 1, 'active': false }
];
_.partition(users, function(o) { return o.active; });
// → objects for [['fred'], ['barney', 'pebbles']]
// The `_.matches` iteratee shorthand.
_.partition(users, { 'age': 1, 'active': false });
// → objects for [['pebbles'], ['barney', 'fred']]
// The `_.matchesProperty` iteratee shorthand.
_.partition(users, ['active', false]);
// → objects for [['barney', 'pebbles'], ['fred']]
// The `_.property` iteratee shorthand.
_.partition(users, 'active');
// → objects for [['fred'], ['barney', 'pebbles']]
R.partition(R.contains('s'), ['sss', 'ttt', 'foo', 'bars']);
// => [ [ 'sss', 'bars' ], [ 'ttt', 'foo' ] ]
R.partition(R.contains('s'), { a: 'sss', b: 'ttt', foo: 'bars' });
// => [ { a: 'sss', foo: 'bars' }, { b: 'ttt' } ]
답변
이를 위해 reduce를 사용할 수 있습니다.
function partition(array, callback){
return array.reduce(function(result, element, i) {
callback(element, i, array)
? result[0].push(element)
: result[1].push(element);
return result;
}, [[],[]]
);
};
최신 정보. ES6 구문을 사용하면 재귀를 사용하여 수행 할 수도 있습니다.
function partition([current, ...tail], f, [left, right] = [[], []]) {
if(current === undefined) {
return [left, right];
}
if(f(current)) {
return partition(tail, f, [[...left, current], right]);
}
return partition(tail, f, [left, [...right, current]]);
}
답변
이것은 Ruby의Enumerable#partition
방법 과 매우 유사하게 들립니다 .
함수가 부작용을 가질 수없는 경우 (즉, 원래 배열을 변경할 수없는 경우), 각 요소를 반복하고 요소를 두 배열 중 하나로 푸시하는 것보다 배열을 분할하는 더 효율적인 방법은 없습니다.
즉, Array
이 기능을 수행 하는 방법을 만드는 것이 틀림없이 더 “우아하다” . 이 예제에서 필터 함수는 원래 배열의 컨텍스트에서 실행되고 (즉, this
원래 배열이 됨) 요소와 요소의 인덱스를 인수로받습니다 ( jQuery의 each
메서드 와 유사 함 ).
Array.prototype.partition = function (f){
var matched = [],
unmatched = [],
i = 0,
j = this.length;
for (; i < j; i++){
(f.call(this, this[i], i) ? matched : unmatched).push(this[i]);
}
return [matched, unmatched];
};
console.log([1, 2, 3, 4, 5].partition(function (n, i){
return n % 2 == 0;
}));
//=> [ [ 2, 4 ], [ 1, 3, 5 ] ]
답변
이 작은 녀석을 생각해 냈습니다. 그것은 당신이 설명한 것과 같은 모든 것을 사용하지만 제 생각에는 깨끗하고 간결 해 보입니다.
//Partition function
function partition(array, filter) {
let pass = [], fail = [];
array.forEach((e, idx, arr) => (filter(e, idx, arr) ? pass : fail).push(e));
return [pass, fail];
}
//Run it with some dummy data and filter
const [lessThan5, greaterThanEqual5] = partition([0,1,4,3,5,7,9,2,4,6,8,9,0,1,2,4,6], e => e < 5);
//Output
console.log(lessThan5);
console.log(greaterThanEqual5);
답변
필터 함수에서 거짓 항목을 함수 외부의 다른 변수로 푸시 할 수 있습니다.
var bad = [], good = [1,2,3,4,5];
good = good.filter(function (value) { if (value === false) { bad.push(value) } else { return true});
물론 value === false
실제 비교가 필요합니다;)
그러나 그것은 forEach
. forEach
더 나은 코드 가독성을 위해 사용해야한다고 생각합니다 .
답변
읽기 쉽습니다.
const partition = (arr, condition) => {
const trues = arr.filter(el => condition(el));
const falses = arr.filter(el => !condition(el));
return [trues, falses];
};
// sample usage
const nums = [1,2,3,4,5,6,7]
const [evens, odds] = partition(nums, (el) => el%2 == 0)