.map()의 요소를 건너뛰는 방법
에서 어레이 요소를 건너뛰려면 어떻게 해야 합니다..map
?
내 코드:
var sources = images.map(function (img) {
if(img.src.split('.').pop() === "json"){ // if extension is .json
return null; // skip
}
else{
return img.src;
}
});
이 값이 반환됩니다.
["img.png", null, "img.png"]
그저..filter()
첫 번째:
var sources = images.filter(function(img) {
if (img.src.split('.').pop() === "json") {
return false; // skip
}
return true;
}).map(function(img) { return img.src; });
만약 당신이 그렇게 하고 싶지 않다면, 그것은 비용이 좀 들기 때문에 불합리하지 않습니다, 당신은 좀 더 일반적인 것을 사용할 수 있다..reduce()
. 일반적으로 표현하실 수 있습니다..map()
측면에서..reduce
:
someArray.map(function(element) {
return transform(element);
});
라고 쓸 수 있다
someArray.reduce(function(result, element) {
result.push(transform(element));
return result;
}, []);
요소를 건너뛸 필요가 있는 경우 를 사용하여 쉽게 할 수 있습니다..reduce()
:
var sources = images.reduce(function(result, img) {
if (img.src.split('.').pop() !== "json") {
result.push(img.src);
}
return result;
}, []);
그 버전에서는, 의 코드는.filter()
첫 번째 샘플은.reduce()
콜백이미지 소스는 필터 조작에 의해 유지되었을 경우에만 결과 배열에 푸시됩니다.
update : 이 질문은 많은 주목을 받고 있습니다.다음의 설명을 덧붙이겠습니다.의 목적.map()
개념으로서 "맵"이 의미하는 바를 정확히 실행하는 것입니다.즉, 특정 규칙에 따라 값 목록을 다른 값 목록으로 변환합니다.도시 몇 개가 완전히 없어지면 어떤 나라의 종이 지도가 이상하게 보일 수 있듯이, 한 목록에서 다른 목록으로 매핑하는 것은 결과 값 세트가 1:1일 때만 의미가 있습니다.
일부 값을 제외한 오래된 목록에서 새 목록을 만드는 것이 의미가 없다고 말하는 것이 아닙니다.난 그냥 확실히 하려고 하는 거야.map()
에는 오래된 값의 변환에 의해 형성된 값만을 사용하여 오래된 배열과 같은 길이의 새 배열을 작성하는 단순한 의도가 있습니다.
2019년부터 Array.protype.platMap은 좋은 옵션입니다.
images.flatMap(({src}) => src.endsWith('.json') ? [] : src);
MDN에서:
flatMap
는 지도에서 항목을 추가 및 제거하는 방법(항목 수 제한)으로 사용할 수 있습니다.즉, 1대 1이 아닌 (각 입력 항목을 개별적으로 처리하여) 많은 항목을 여러 항목에 매핑할 수 있습니다.그런 의미에서 필터와 반대로 작용합니다.항목을 보관할 1-element 어레이, 항목을 추가할 다중 요소 어레이 또는 항목을 제거할 0-element 어레이를 반환하기만 하면 됩니다.
배열에서 몇 가지 요소를 건너뛰는 가장 간단한 방법은 filter() 메서드를 사용하는 것이라고 생각합니다.
이 메서드(ES5)와 ES6 구문을 사용하면 코드를 한 줄에 쓸 수 있습니다.그러면 원하는 것이 반환됩니다.
let images = [{src: 'img.png'}, {src: 'j1.json'}, {src: 'img.png'}, {src: 'j2.json'}];
let sources = images.filter(img => img.src.slice(-4) != 'json').map(img => img.src);
console.log(sources);
TLDR: 먼저 어레이를 필터링한 후 맵을 실행할 수 있지만, 이 작업을 수행하려면 어레이에 두 번 통과해야 합니다(필터는 매핑할 어레이를 반환합니다).이 어레이는 작기 때문에 퍼포먼스 비용은 매우 낮습니다.단순하게 줄일 수도 있습니다.단, 어레이(또는 임의의 데이터형)를 1회 통과하는 것으로 이것을 실현하는 방법을 재상상화하려면 , Rich Hickey가 개발한 「트랜스듀서」라고 하는 아이디어를 사용할 수 있습니다.
답변:
할 필요는 .[].map(fn1).filter(f2)...
에서는, 모든 「에 에,reducing
★★★★★★ 。
가장 좋은 방법은 실제 축소 기능으로 작동하기 때문에 데이터 패스는 1개뿐이며 추가 어레이는 없습니다.
는 '감소함수'로입니다.reduce
합니다.
// 1. create a concat reducing function that can be passed into `reduce`
const concat = (acc, input) => acc.concat([input])
// note that [1,2,3].reduce(concat, []) would return [1,2,3]
// transforming your reducing function by mapping
// 2. create a generic mapping function that can take a reducing function and return another reducing function
const mapping = (changeInput) => (reducing) => (acc, input) => reducing(acc, changeInput(input))
// 3. create your map function that operates on an input
const getSrc = (x) => x.src
const mappingSrc = mapping(getSrc)
// 4. now we can use our `mapSrc` function to transform our original function `concat` to get another reducing function
const inputSources = [{src:'one.html'}, {src:'two.txt'}, {src:'three.json'}]
inputSources.reduce(mappingSrc(concat), [])
// -> ['one.html', 'two.txt', 'three.json']
// remember this is really essentially just
// inputSources.reduce((acc, x) => acc.concat([x.src]), [])
// transforming your reducing function by filtering
// 5. create a generic filtering function that can take a reducing function and return another reducing function
const filtering = (predicate) => (reducing) => (acc, input) => (predicate(input) ? reducing(acc, input): acc)
// 6. create your filter function that operate on an input
const filterJsonAndLoad = (img) => {
console.log(img)
if(img.src.split('.').pop() === 'json') {
// game.loadSprite(...);
return false;
} else {
return true;
}
}
const filteringJson = filtering(filterJsonAndLoad)
// 7. notice the type of input and output of these functions
// concat is a reducing function,
// mapSrc transforms and returns a reducing function
// filterJsonAndLoad transforms and returns a reducing function
// these functions that transform reducing functions are "transducers", termed by Rich Hickey
// source: http://clojure.com/blog/2012/05/15/anatomy-of-reducer.html
// we can pass this all into reduce! and without any intermediate arrays
const sources = inputSources.reduce(filteringJson(mappingSrc(concat)), []);
// [ 'one.html', 'two.txt' ]
// ==================================
// 8. BONUS: compose all the functions
// You can decide to create a composing function which takes an infinite number of transducers to
// operate on your reducing function to compose a computed accumulator without ever creating that
// intermediate array
const composeAll = (...args) => (x) => {
const fns = args
var i = fns.length
while (i--) {
x = fns[i].call(this, x);
}
return x
}
const doABunchOfStuff = composeAll(
filtering((x) => x.src.split('.').pop() !== 'json'),
mapping((x) => x.src),
mapping((x) => x.toUpperCase()),
mapping((x) => x + '!!!')
)
const sources2 = inputSources.reduce(doABunchOfStuff(concat), [])
// ['ONE.HTML!!!', 'TWO.TXT!!!']
여기 재미있는 해결책이 있습니다.
/**
* Filter-map. Like map, but skips undefined values.
*
* @param callback
*/
function fmap(callback) {
return this.reduce((accum, ...args) => {
const x = callback(...args);
if(x !== undefined) {
accum.push(x);
}
return accum;
}, []);
}
바인드 연산자와 함께 사용:
[1,2,-1,3]::fmap(x => x > 0 ? x * 2 : undefined); // [2,4,6]
각 루프를 사용하면 어떨까요?
let arr = ['a', 'b', 'c', 'd', 'e'];
let filtered = [];
arr.forEach(x => {
if (!x.includes('b')) filtered.push(x);
});
console.log(filtered) // filtered === ['a','c','d','e'];
또는 더 간단한 필터 사용:
const arr = ['a', 'b', 'c', 'd', 'e'];
const filtered = arr.filter(x => !x.includes('b')); // ['a','c','d','e'];
불필요한 엣지 케이스에 대한 답변:
const thingsWithoutNulls = things.reduce((acc, thing) => {
if (thing !== null) {
acc.push(thing);
}
return acc;
}, [])
var sources = images.map(function (img) {
if(img.src.split('.').pop() === "json"){ // if extension is .json
return null; // skip
}
else{
return img.src;
}
}).filter(Boolean);
.filter(Boolean)
는 특정 배열 을 모두 이 falsey 값은 "falsey"입니다.★★★★★★★★★★★★★★★★★★·null
.
펠릭스 클링의 코멘트를 추정하려면.filter()
음음음같 뭇매하다
var sources = images.map(function (img) {
if(img.src.split('.').pop() === "json") { // if extension is .json
return null; // skip
} else {
return img.src;
}
}).filter(Boolean);
이 falsey에 의해 됩니다..map()
다음과 같이 심플화할 수 있습니다.
var sources = images.map(function (img) {
if(img.src.split('.').pop() !== "json") { // if extension is .json
return img.src;
}
}).filter(Boolean);
또는 화살표 기능, 물체 파괴 기능 및 원라이너로 사용할 수도 있습니다.&&
★★★★★★★★★★★★★★★★★★:
var sources = images.map(({ src }) => src.split('.').pop() !== "json" && src).filter(Boolean);
다음으로 null 이외의 값만 매핑하는 유틸리티 메서드(ES5 호환)를 나타냅니다(절감하는 콜 숨김).
function mapNonNull(arr, cb) {
return arr.reduce(function (accumulator, value, index, arr) {
var result = cb.call(null, value, index, arr);
if (result != null) {
accumulator.push(result);
}
return accumulator;
}, []);
}
var result = mapNonNull(["a", "b", "c"], function (value) {
return value === "b" ? null : value; // exclude "b"
});
console.log(result); // ["a", "c"]
1행 ES5/ES6에서 늘 또는 정의되지 않은 경우
//will return array of src
images.filter(p=>!p.src).map(p=>p.src);//p = property
//in your condition
images.filter(p=>p.src.split('.').pop() !== "json").map(p=>p.src);
용 i i i i를 쓴다..forEach
results
후 이에서는 I not over array over array를 사용합니다.
어프터 어프터 어프터 어프터 어프터 어프터 어프터 어프터 어프터 어프터 어프터 어프터 어프터 map()
★★filter()
예를 들어 다음과 같습니다.
var sources = images.map(function (img) {
if(img.src.split('.').pop() === "json"){ // if extension is .json
return null; // skip
}
else {
return img.src;
}
});
메서드 필터:
const sourceFiltered = sources.filter(item => item)
만 새 .sourceFiltered
.
다음은 @theprtk에서 제공하는 코드의 업데이트 버전입니다.예를 들어 일반화된 버전을 보여주기 위해 조금 정리한 것입니다.
주의: 이 글을 투고에 코멘트로 추가하고 싶지만 아직 평판이 좋지 않습니다.
/**
* @see http://clojure.com/blog/2012/05/15/anatomy-of-reducer.html
* @description functions that transform reducing functions
*/
const transduce = {
/** a generic map() that can take a reducing() & return another reducing() */
map: changeInput => reducing => (acc, input) =>
reducing(acc, changeInput(input)),
/** a generic filter() that can take a reducing() & return */
filter: predicate => reducing => (acc, input) =>
predicate(input) ? reducing(acc, input) : acc,
/**
* a composing() that can take an infinite # transducers to operate on
* reducing functions to compose a computed accumulator without ever creating
* that intermediate array
*/
compose: (...args) => x => {
const fns = args;
var i = fns.length;
while (i--) x = fns[i].call(this, x);
return x;
},
};
const example = {
data: [{ src: 'file.html' }, { src: 'file.txt' }, { src: 'file.json' }],
/** note: `[1,2,3].reduce(concat, [])` -> `[1,2,3]` */
concat: (acc, input) => acc.concat([input]),
getSrc: x => x.src,
filterJson: x => x.src.split('.').pop() !== 'json',
};
/** step 1: create a reducing() that can be passed into `reduce` */
const reduceFn = example.concat;
/** step 2: transforming your reducing function by mapping */
const mapFn = transduce.map(example.getSrc);
/** step 3: create your filter() that operates on an input */
const filterFn = transduce.filter(example.filterJson);
/** step 4: aggregate your transformations */
const composeFn = transduce.compose(
filterFn,
mapFn,
transduce.map(x => x.toUpperCase() + '!'), // new mapping()
);
/**
* Expected example output
* Note: each is wrapped in `example.data.reduce(x, [])`
* 1: ['file.html', 'file.txt', 'file.json']
* 2: ['file.html', 'file.txt']
* 3: ['FILE.HTML!', 'FILE.TXT!']
*/
const exampleFns = {
transducers: [
mapFn(reduceFn),
filterFn(mapFn(reduceFn)),
composeFn(reduceFn),
],
raw: [
(acc, x) => acc.concat([x.src]),
(acc, x) => acc.concat(x.src.split('.').pop() !== 'json' ? [x.src] : []),
(acc, x) => acc.concat(x.src.split('.').pop() !== 'json' ? [x.src.toUpperCase() + '!'] : []),
],
};
const execExample = (currentValue, index) =>
console.log('Example ' + index, example.data.reduce(currentValue, []));
exampleFns.raw.forEach(execExample);
exampleFns.transducers.forEach(execExample);
당신은 이걸 할 수 있다.
var sources = [];
images.map(function (img) {
if(img.src.split('.').pop() !== "json"){ // if extension is not .json
sources.push(img.src); // just push valid value
}
});
용 i i i i를 쓴다.foreach()
:
var sources = [];
images.forEach(function (img) {
if(img.src.split('.').pop() !== "json"){ // if extension is .json
sources.push(img);
}
});
메모: 당신의 논리를 부정했습니다.
다음과 같이 맵 + 필터를 사용할 수 있습니다.
var sources = images.map(function (img) {
if(img.src.split('.').pop() === "json"){ // if extension is .json
return null; // skip
}
else{
return img.src;
}})?.filter(x => x !== null);
const arr = [0, 1, '', undefined, false, 2, undefined, null, , 3, NaN];
const filtered = arr.filter(Boolean);
console.log(filtered);
/*
Output: [ 1, 2, 3 ]
*/
은 '''를 하는 것입니다.filter
+map
입력 어레이를 동시에 1회 반복할 수 있습니다.그러기 위해서는 어레이를 (내부적으로는) 반복 가능한 것으로 취급해야 합니다.
아래 답변은 이미지를 처리하기 위해 반복 작업 라이브러리를 사용합니다.
import {pipe, filter, map} from 'iter-ops';
const result = pipe(
images,
filter(img => img.src.split('.').pop() !== 'json'),
map(img => img.src)
);
console.log('result:', [...result]);
추신: 저는 '반복수술'의 전자저자입니다.
언급URL : https://stackoverflow.com/questions/24806772/how-to-skip-over-an-element-in-map
'programing' 카테고리의 다른 글
HTML5 캔버스를 서버에 이미지로 저장하는 방법 (0) | 2022.10.29 |
---|---|
jQuery를 사용하여 페이지 로드 시 양식 입력 텍스트 필드에 초점을 맞추는 방법은 무엇입니까? (0) | 2022.10.29 |
MariaDB JDBC 클라이언트로깅 (0) | 2022.10.29 |
Java HTTP 클라이언트 요청(타임아웃이 정의됨) (0) | 2022.10.29 |
PhpMyAdmin을 사용한 Nginx(SSL을 통해 보안 보호) (0) | 2022.10.29 |