Фильтрация массивов в JS, от простой фильтрации до фильтрации по нескольким условиям

интервью внешний интерфейс алгоритм JavaScript

Когда я работал в предыдущей компании, было требование выполнить функцию скрининга во фронтальной части, получить все данные за один раз, а потом фильтровать по условиям. Обычно скрининг обеспечивается фоном к интерфейсу.В случае небольшого объема данных некоторые люди могут столкнуться с ситуацией скрининга фронтенда.Я написал эту статью, чтобы поделиться ею с вами.Если у вас есть какие-либо вопросы , пожалуйста, указывайте и учитесь друг у друга.

В общем, для скрининга по одному условию метод фильтрации массива может соответствовать требованиям.В этой статье основное внимание уделяется сложному скринингу при нескольких условиях, и перечислены несколько связанных точек знаний.

Здесь много 🌰🌰🌰🌰


// 这个是例子中的被筛选数组
var aim = [
    {name:'Anne', age: 23, gender:'female'},
    {name:'Leila', age: 16, gender:'female'},
    {name:'Jay', age: 19, gender:'male'},
    {name:'Mark', age: 40, gender:'male'}
]

Фильтр данных с одним условием

Фильтруйте по одному имени, используйте метод фильтра, чтобы определить, является ли имя целевым именем.


// 根据单个名字筛选
function filterByName(aim, name) {
    return aim.filter(item => item.name == name)
}
// 输入 aim 'Leila' 期望输出为 [{name:'Leila', age: 16, gender:'female'}]
console.log(filterByName(aim,'leila'))

Фильтр нескольких данных с одним условием

Фильтруйте по нескольким именам. Здесь нужно использовать цикл for для обхода целевого массива, а затем использовать метод find, чтобы найти его и поместить в массив результатов. Метод find также может получить желаемый результат, даже если имя то же. Цикл for можно заменить некоторыми методами обхода массива, а код можно упростить, например, для выражения смысла.


// 根据多个名字筛选
function filterByName1(aim, nameArr) {
    let result = []
    for(let i = 0; i < nameArr.length; i++) {
        result.push(aim.find(item => item.name = nameArr[i]))
    }
    return result
}
// 输入 aim ['Anne','Jay'] 
//期望输出为 [{name:'Anne', age: 23, gender:'female'},{name:'Jay', age: 19, gender:'male'}]
console.log(filterByName1(aim,['Leila','Jay']))
// 有BUG 改进后

Единый фильтр данных с несколькими условиями

Отфильтруйте по одному имени или одному возрасту и используйте метод фильтрации, чтобы определить взаимосвязь между условиями.


// 根据名字或者年龄筛选
function filterByName2(aim, name, age) {
    return aim.filter(item => item.name == name || item.age == age)
}
console.log(filterByName2(aim,'Leila',19))

Фильтрация нескольких данных с несколькими условиями

Сначала я сделал это с тупым двойным циклом for и обнаружил, что он медленный и не дает желаемого эффекта. Конкретное ментальное путешествие слишком далеко, поэтому кратко представлен следующий алгоритм фильтрации.

Первый — запихнуть все условия фильтрации в один объект, с помощью метода keys объекта object получить имя условия фильтрации, а какое условие нужно отфильтровать, какое имя? возраст пол?

Затем используйте метод filter для фильтрации целевых данных 🌰 следующим образом⬇️

Фильтр по имени и возрасту


//根据名字和年龄多元素筛选
export function multiFilter(array, filters) {
  const filterKeys = Object.keys(filters)
  // filters all elements passing the criteria
  return array.filter((item) => {
    // dynamically validate all filter criteria
    return filterKeys.every(key => {
        //ignore when the filter is empty Anne
      if(!filters[key].length) return true
      return !!~filters[key].indexOf(item[key])
    })
  })
}
/*
 * 这段代码并非我原创,感兴趣的可以去原作者那里点个赞
 * 作者是:@author https://gist.github.com/jherax
 * 这段代码里我只加了一行,解决部分筛选条件清空时候整体筛选失效的问题
 */

var filters = {
    name:['Leila', 'Jay'],
    age:[]
}
/* 结果:
 * [{name: "Leila", age: 16, gender: "female"},
 *  {name: "Jay", age: 19, gender: "male"}]
 */

Например, здесь оценивается, находится ли значение имени каждого данных в массиве filter.name. Если это так, он возвращает true.Если оценивается, что filter.age является пустым массивом, он возвращает true напрямую , Получите правильные данные фильтра.

Точка знаний 1: Object.key() получает индекс массива или свойство объекта


var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); 
// ["0", "1", "2"]


var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); 
// ["0", "1", "2"]


var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); 
// ["2", "7", "100"] 猜猜为啥?

Пункт знаний 2: ложь в js

falsy : 0 , false, "", null, undefined, NaN

В суждении только 6 вышеуказанных случаев будут ложными, остальные верны

var a;
if(a!=null&&typeof(a)!=undefined&&a!=''){
    //a有内容才执行的代码  
}

if(!!a){
    //a有内容才执行的代码...  
}

Пункт знаний 3: разница между Array.every и Array.some

Насколько я понимаю, при переборе массива:

Array.everyУсловие представляет собой отношение «и», все верно истинно, а условие истинно, оно истинно, и если есть ложное, оно возвращает ложное

Array.someУсловие представляет собой отношение "или", true равно true, если одно из условий истинно, возвращает true, а если все условия ложны, возвращает false

Вот пример 🌰


// 判断每个名字都为Anne?
let dataEvery = aim.every(item => item.name === 'Anne') // false
let dataEvery = aim.some(item => item.name === 'Anne') // true

// 判断每个名字都是字符串?
let dataEvery = aim.every(item => typeof item.name === 'string') // true
let dataEvery = aim.some(item => typeof item.name === 'string') // true

Пункт знаний 4: глубокая копия и поверхностная копия массива

Недавно я участвовал в нескольких фронтенд-интервью, и один из моих любимых вопросов — глубокое копирование или поверхностное копирование. В одном вопросе рассматриваются типы данных, операции с массивами, рекурсивные алгоритмы и т. д.

Поскольку массив является ссылочным типом в js, ссылочное отношение копируется при простом копировании. При фильтрации полученных данных я не хочу влиять на исходные данные, поэтому я использую «глубокую копию», чтобы получить данные с той же структурой данных и независимо от исходных данных, вместо того, чтобы просто копировать их ссылочные отношения.


// 我常用方法,如果项目很大,不推荐
let obj1 = JSON.parse(JSON.stringify(obj))

// deepclone
function deepClone(o1, o2) {
    for (let k in o2) {
        if (typeof o2[k] === 'object') {
            o1[k] = {};
            deepClone(o1[k], o2[k]);
        } else {
            o1[k] = o2[k];
        }
    }
}

Подумайте об этом: оптимизация рекурсивных алгоритмов

Этот пункт знаний имеет мало общего с этой статьей. 😄 Извините за предыдущее заблуждение.

Это то, что я увидел в буклете Nuggets по фронтенду. Когда я говорил об алгоритме, я упомянул оптимизацию рекурсивного алгоритма. Я был удивлен, когда впервые увидел его, и я не использовал его в проект. Если интересно, можете попробовать, это сумма последовательности Фибоначчи. Можете сами набрать в браузере, и попробовать разницу в количестве операций без кеша и с кешем.

let count = 0;
function fn(n) {
    let cache = {};
    function _fn(n) {
        if (cache[n]) {
            return cache[n];
        }
        count++;
        if (n == 1 || n == 2) {
            return 1;
        }
        let prev = _fn(n - 1);
        cache[n - 1] = prev;
        let next = _fn(n - 2);
        cache[n - 2] = next;
        return prev + next;
    }
    return _fn(n);
}

let count2 = 0;
function fn2(n) {
    count2++;
    if (n == 1 || n == 2) {
        return 1;
    }
    return fn2(n - 1) + fn2(n - 2);
}

Заканчивать!