Удаление элементов с массивом.карты в JavaScript
Я хотел бы отфильтровать массив элементов с помощью
6 ответов
вы должны использовать filter
метод, а не карта, Если вы не хотите изменять элементы массива, в дополнение к фильтрации.
например.
var filteredItems = items.filter(function(item)
{
return ...some condition...;
});
[Edit: конечно, вы всегда можете сделать sourceArray.filter(...).map(...)
как фильтровать, так и мутировать]
я писал этот ответ некоторое время назад, и мое мнение изменилось. Я рекомендую проверить мой блоге что расширяет эту тему и объясняет ее намного лучше. Он также дает сравнение JSperf в конце альтернатив.
tl; dr это:
Чтобы выполнить то, что вы просите (фильтрация и сопоставление в одном вызове функции), вы должны использовать Array.reduce()
. Однако более читабельным и обычно быстрее подход состоит в том, чтобы просто использовать фильтр и карту, скованные вместе:
[1,2,3].filter(num => num > 2).map(num => num * 2)
ниже приводится описание того, как Array.reduce()
работает, и как его можно использовать для выполнения filter и map в одну итерацию. Если это слишком сжато, я настоятельно рекомендую увидеть сообщение в блоге, связанное выше, что является гораздо более дружественным вступлением с четкими примерами и прогрессией.
вы даете уменьшить аргумент, который является (обычно анонимным) функция.
это анонимная функция принимает два параметра-один (например, анонимные функции, переданные в map/filter / forEach), является итерацией для работы. Существует еще один аргумент для анонимной функции, переданной для уменьшения, однако, что эти функции не принимают, и это значение, которое будет передаваться между вызовами функций, часто называемое memo.
обратите внимание, что в то время как массив.фильтр() принимает только один аргумент (функцию), Array.reduce () также принимает важный (хотя и необязательный) второй аргумент: начальное значение для "memo", которое будет передано в эту анонимную функцию в качестве ее первого аргумента, а затем может быть изменено и передано между вызовами функций. (Если он не указан, то "memo" в первом анонимном вызове функции по умолчанию будет первым iteratee, а аргумент "iteratee" фактически будет вторым значением в массиве)
в нашем случай, мы передадим пустой массив для начала, а затем выберем, вводить ли нашу итерацию в наш массив или нет на основе нашей функции-это процесс фильтрации.
наконец, мы вернем наш "массив в процессе" при каждом анонимном вызове функции, и reduce примет это возвращаемое значение и передаст его в качестве аргумента (называемого memo) к следующему вызову функции.
это позволяет фильтру и карте произойти в одной итерации, сокращая наше количество необходимых итераций в половина. :)
для более полного объяснения обратитесь к MDN или по ссылке выше. :)
основной пример вызова Reduce:
let array = [1,2,3];
const initialMemo = [];
array = array.reduce((memo, iteratee) => {
// if condition is our filter
if (iteratee > 1) {
// what happens inside the filter is the map
memo.push(iteratee * 2);
}
// this return value will be passed in as the 'memo' argument
// to the next call of this function, and this function will have
// every element passed into it at some point.
return memo;
}, initialMemo)
console.log(array) // [4,6], equivalent to [(2 * 2), (3 * 2)]
более сжатом варианте:
[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
обратите внимание, что первая итерация была не больше единицы и поэтому была отфильтрована. Также обратите внимание на initialMemo, названный просто, чтобы сделать его существование ясным и привлечь к нему внимание. Еще раз, он передается как "memo" к первому анонимному вызову функции, а затем возвращаемое значение анонимной функции передается в качестве аргумента memo следующей функции.
Другим примером классического варианта использования memo будет возврат наименьшего или наибольшего числа в массиве. Пример:
[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
// ^this would return the largest number in the list.
пример того, как написать свою собственную функцию уменьшения (это часто помогает понять такие функции, я нахожу):
test_arr = [];
// we accept an anonymous function, and an optional 'initial memo' value.
test_arr.my_reducer = function(reduceFunc, initialMemo) {
// if we did not pass in a second argument, then our first memo value
// will be whatever is in index zero. (Otherwise, it will
// be that second argument.)
const initialMemoIsIndexZero = arguments.length < 2;
// here we use that logic to set the memo value accordingly.
let memo = initialMemoIsIndexZero ? this[0] : initialMemo;
// here we use that same boolean to decide whether the first
// value we pass in as iteratee is either the first or second
// element
const initialIteratee = initialMemoIsIndexZero ? 1 : 0;
for (var i = initialIteratee; i < this.length; i++) {
// memo is either the argument passed in above, or the
// first item in the list. initialIteratee is either the
// first item in the list, or the second item in the list.
memo = reduceFunc(memo, this[i]);
}
// after we've compressed the array into a single value,
// we return it.
return memo;
}
реальная реализация позволяет получить доступ к таким вещам, как индекс, например, но я надеюсь, это поможет вам получить незамысловатое ощущение сути этого.
Это не то, что карта делает. Вы действительно хотите массив.фильтр. Или, если вы действительно хотите удалить элементы из исходного списка, вам нужно будет сделать это императивно с циклом for.
вы должны отметить, однако, что Array.filter
Не поддерживается во всех браузерах, поэтому вы должны прототипировать:
//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp*/)
{
var len = this.length;
if (typeof fun != "function")
throw new TypeError();
var res = new Array();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this)
{
var val = this[i]; // in case fun mutates this
if (fun.call(thisp, val, i, this))
res.push(val);
}
}
return res;
};
}
и делая это, вы можете создать прототип любого метода, который вам может понадобиться.
Я размещаю этот ответ здесь, потому что общие поля на этой странице ужасны
function reduce(f, y, xs, context) {
var acc = y;
for (var i = 0, len = xs.length; i < len; i++)
acc = f.call(context, acc, xs[i], i, xs);
return acc;
}
function reduce1(f, xs, context) {
if (xs.length === 0)
throw Error('cannot reduce empty array without initial value');
else
return reduce(f, xs[0], xs.slice(1), context);
}
function map(f, xs, context) {
return reduce(function(acc, x, i) {
return acc.concat([
f.call(context, x, i, xs)
]);
}, [], xs);
}
function filter(f, xs, context) {
return reduce(function(acc, x, i) {
if (f.call(context, x, i, xs))
return acc.concat([x]);
else
return acc;
}, [], xs);
}
продлить прототипов
if (Array.prototype.reduce === undefined) {
Array.prototype.reduce = function(f, initialValue, context) {
if (initialValue === undefined)
return reduce1(f, this, context);
else
return reduce(f, initialValue, this, context);
};
}
if (Array.prototype.map === undefined) {
Array.prototype.map = function(f, context) {
return map(f, this, context);
};
}
if (Array.prototype.filter === undefined) {
Array.prototype.filter = function(f, context) {
return filter(f, this, context);
};
}
var arr = [1,2,'xxx','yyy']
arr = arr.filter(function(e){ return e != 'xxx' });
arr // [1, 2, "yyy"]