배열을 필터 함수로 나눕니다.
각 가 를 두 .true
아니면false
은 .array.filter
, 하지만 저는 걸러진 요소들도 손에 쥐고 싶습니다.
를 입니다.array.forEach
각 요소에서 술어 함수를 호출합니다.이것이 참인지 거짓인지에 따라 현재 요소를 두 개의 새로운 배열 중 하나에 밀어 넣겠습니다.더 우아하거나 더 나은 방법이 있을까요?array.filter
서 는다를 .false
요?
ES6를 사용하면 확산 구문을 다음과 같이 줄일 수 있습니다.
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' } ]
내가 생각해낸 작은 남자.말씀하신 것처럼 하나하나 다 쓰이지만, 제 생각에는 깨끗하고 간결해 보입니다.
//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);
축소를 사용할 수 있습니다.
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;
}, [[],[]]
);
};
또는 타이프스크립트를 사용하는 경우:
const partition = <T,>(
array: T[],
callback: (element: T, index: number, array: T[]) => boolean
) => {
return array.reduce(function(result, element, i) {
callback(element, i, array)
? result[0].push(element)
: result[1].push(element);
return result;
}, [[],[]]);
};
예:
const groceries = [
{ type: "apple" },
{ type: "pear" },
{ type: "banana" }
]
const [apples, others] = partition(
groceries,
(item) => item.type === "apple",
);
// => apples: [{ type: "apple" }]
// => others: [{ type: "pear" }, { type: "banana" }]
ES6 구문을 사용하면 재귀(매번 반복할 때마다 새 배열을 만들지 않도록 업데이트됨)를 사용하여 다음과 같은 작업을 수행할 수도 있습니다.
function partition([current, ...tail], f, left = [], right = []) {
if(current === undefined) {
return [left, right];
}
if(f(current)) {
left.push(current);
return partition(tail, f, left, right);
}
right.push(current);
return partition(tail, f, left, right);
}
이것은 루비의 방법과 매우 비슷하게 들립니다.
함수가 부작용을 일으킬 수 없는 경우(즉, 원래 배열을 변경할 수 없는 경우), 각 요소를 반복하여 요소를 두 개의 배열 중 하나로 밀어 넣는 것보다 더 효율적인 배열 분할 방법은 없습니다.
는 하지만, 에 대한 방법을 만드는 이 "" 고하는 더고 말할 수 있습니다.Array
이 기능을 수행할 수 있습니다.됩니다(즉))에서this
원래 배열)이 될 것이며, 요소와 요소의 인덱스를 인수로 받습니다(jQuery의 메서드와 유사).
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 ] ]
필터 함수에서는 거짓 항목을 다른 변수 외부 함수에 밀어 넣을 수 있습니다.
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
더 나은 코드 가독성을 위해.
서 많은 됩니다.Array.prototype.reduce
가변 어큐뮬레이터를 구축하고, 대규모 어레이의 경우 각 반복마다 새로운 어레이를 복사하기 위해 스프레드 연산자를 사용하는 것보다 이것이 더 효율적이라는 점을 정확하게 지적합니다.단점은 짧은 람다 구문을 사용하는 "순수한" 표현만큼 예쁘지 않다는 것입니다.
하지만 그 방법은 쉼표 연산자를 사용하는 것입니다.C 언어에서 쉼표는 항상 오른쪽 피연산자를 반환하는 연산자입니다.이를 통해 void 함수를 호출하고 값을 반환하는 식을 만들 수 있습니다.
function partition(array, predicate) {
return array.reduce((acc, item) => predicate(item)
? (acc[0].push(item), acc)
: (acc[1].push(item), acc), [[], []]);
}
부울 식이 0과 1의 숫자를 암시적으로 캐스트한다는 점을 이용하면, 더 간결하게 표현할 수 있습니다. 비록 제가 보기에는 그렇게 가독성이 있다고 생각하지는 않지만 말입니다.
function partition(array, predicate) {
return array.reduce((acc, item) => (acc[+!predicate(item)].push(item), acc), [[], []]);
}
용도:
const [trues, falses] = partition(['aardvark', 'cat', 'apple'], i => i.startsWith('a'));
console.log(trues); // ['aardvark', 'apple']
console.log(falses); // ['cat']
이거는?
[1,4,3,5,3,2].reduce( (s, x) => { s[ x > 3 ].push(x); return s;} , {true: [], false:[]} )
아마도 이것이 퍼짐 연산자보다 더 효율적일 것입니다.
아니면 조금 더 짧지만 더 못생겼습니다.
[1,4,3,5,3,2].reduce( (s, x) => s[ x > 3 ].push(x)?s:s , {true: [], false:[]} )
시도해 보기:
function filter(a, fun) {
var ret = { good: [], bad: [] };
for (var i = 0; i < a.length; i++)
if (fun(a[i])
ret.good.push(a[i]);
else
ret.bad.push(a[i]);
return ret;
}
데모
읽기 쉬운 것.
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)
이해하기 쉽기 때문에 이렇게 하게 되었습니다.
const partition = (array, isValid) => {
const pass = []
const fail = []
array.forEach(element => {
if (isValid(element)) {
pass.push(element)
} else {
fail.push(element)
}
})
return [pass, fail]
}
// usage
const [pass, fail] = partition([1, 2, 3, 4, 5], (element) => element > 3)
그리고 타이프스크립트 유형을 포함한 동일한 방법:
const partition = <T>(array: T[], isValid: (element: T) => boolean): [T[], T[]] => {
const pass: T[] = []
const fail: T[] = []
array.forEach(element => {
if (isValid(element)) {
pass.push(element)
} else {
fail.push(element)
}
})
return [pass, fail]
}
// usage
const [pass, fail] = partition([1, 2, 3, 4, 5], (element: number) => element > 3)
원-라이너 파티션
const partitionBy = (arr, predicate) =>
arr.reduce((acc, item) => (acc[+!predicate(item)].push(item), acc), [[], []]);
데모
// to make it consistent to filter pass index and array as arguments
const partitionBy = (arr, predicate) =>
arr.reduce(
(acc, item, index, array) => (
acc[+!predicate(item, index, array)].push(item), acc
),
[[], []]
);
console.log(partitionBy([1, 2, 3, 4, 5], x => x % 2 === 0));
console.log(partitionBy([..."ABCD"], (x, i) => i % 2 === 0));
Typescript(v4.5)용
const partitionBy = <T>(
arr: T[],
predicate: (v: T, i: number, ar: T[]) => boolean
) =>
arr.reduce(
(acc, item, index, array) => {
acc[+!predicate(item, index, array)].push(item);
return acc;
},
[[], []] as [T[], T[]]
);
여기서 대부분의 답은 단순히 Array.reduce를 변형한 것으로 이를 수행하는 올바른 방법입니다.자바스크립트에서 배열을 분할하기 위한 간단한 API로 이 모든 것을 추상화하는 작은 라이브러리를 작성했습니다.또한 웹 워커(또는 노드의 웹 쓰레드)를 생성하여 어레이를 파티션 비동기화할 수 있습니다.
const someArray = [1, ... , 100]
console.log('--- start ---');
const reduced = someArray.reduce((reducer, i) => {
// Different variations of fancy code can go here that all do the same thing
if (i < 33) reducer[0].push(i)
else if (i => i > 32 && i < 66) reducer[1].push(i)
else if (i => i > 67) reducer[2].push(i)
return reducer
}, [[], [], []])
console.log('array.reduce done processing');
console.log('--- UI element loaded ---');
'--- start ---'
'array.reduce done processing'
'--- UI element loaded ---'
라이브러리를 사용하여 동일한 작업을 수행하는 방법은 다음과 같습니다.
const someArray = [1, ... , 100]
console.log('--- start ---');
partition()
.async()
.add(i => i < 33)
.add(i => i > 32 && i < 66)
.add(i => i > 67)
.split(someArray)
.then(result => {
console.log('Partitions done processing');
});
console.log('--- UI element loaded ---');
'--- start ---'
'--- UI element loaded ---'
'Partitions done processing'
둘 다의 출력은 세 개의 배열 파티션이 됩니다.
[
[1, ..., 32],
[33, ..., 65],
[66, ..., 100]
]
@Yaremenko Andrii의 첫 번째 솔루션과 동일하지만 구문이 더 짧은 Lodash 파티션 대안
function partition(arr, callback) {
return arr.reduce(
(acc, val, i, arr) => {
acc[callback(val, i, arr) ? 0 : 1].push(val)
return acc
},
[[], []]
)
}
이미 여러 개의 솔루션이 있다는 것을 알고 있지만 위의 답변 중 가장 좋은 부분을 자유롭게 조합하여 Typescript에 확장 방법을 사용했습니다.복사해서 붙여넣기만 하면 작동합니다.
declare global {
interface Array<T> {
partition(this: T[], predicate: (e: T) => boolean): T[][];
}
}
if(!Array.prototype.partition){
Array.prototype.partition = function<T>(this: T[], predicate: (e: T) => boolean): T[][] {
return this.reduce<T[][]>(([pass, fail], elem) => {
(predicate(elem) ? pass : fail).push(elem);
return [pass, fail];
}, [[], []]);
}
}
용도:
const numbers = [1, 2, 3, 4, 5, 6];
const [even, odd] = numbers.partition(n => n % 2 === 0);
언급URL : https://stackoverflow.com/questions/11731072/dividing-an-array-by-filter-function
'programing' 카테고리의 다른 글
md-table - 열 너비 업데이트 방법 (0) | 2023.10.11 |
---|---|
sql 문의 변수가 쿼리를 중단시킵니다. (0) | 2023.10.11 |
setInterval loop을 즉시 시작하는 방법은? (0) | 2023.10.11 |
중앙 하나와 오른쪽/왼쪽 정렬 다른 플렉스박스 요소 (0) | 2023.10.11 |
MySQL: 보기 대 저장 프로시저 (0) | 2023.10.11 |