В обычном Javascript, пытаясь отфильтровать несколько значений в массиве, который содержит объекты пользователя, которые содержат другие объекты и массивы - PullRequest
2 голосов
/ 01 мая 2020

спасибо, что взглянули на это. Извините за длину, пытаюсь быть понятным!

ЧТО Я ПЫТАЮСЬ СДЕЛАТЬ: У меня есть массив пользователей (каждый пользователь - объект), и я пытаюсь отфильтровать пользователей по нескольким критерии («мужчины из Франции» или «женщины из Испании и Соединенных Штатов с инженерными навыками» и т. д. c), но до сих пор это доказано за пределами моих навыков.

Сложность заключалась в том, что пользователи являются объектами в массиве User, но в каждом пользовательском объекте некоторые значения являются дополнительными объектами или массивами. Вот как выглядит массив пользовательских данных (сокращенно):

let users = [
{ 
gender: 'male', 
location: {street: 'Clement Street', country: 'United States'},
skills: ['engineering', 'underwater'], 
}, ...

Обратите внимание, что пол - это просто обычное свойство / значение, но страна находится внутри объекта местоположения, а навыки - в массиве.

У меня уже есть интерфейс кнопок поиска, который создает кнопки переключения для поиска по каждому доступному критерию, и каждый раз, когда вы нажимаете кнопку, я добавляю или удаляю эти критерии в объекте фильтра. Объект фильтра выглядит следующим образом и использует массивы внутри него, так что я могу определить несколько критериев одновременно, например, несколько стран для поиска, несколько навыков и т. Д. c .:

    filter: {
        gender: ['female'],
    location: {
    country: ['Spain'],},
    skills: ['optics', ]
    },

ГДЕ Я ДЕЙСТВИТЕЛЬНО ПОЛУЧИЛ STUCK Я создал метод filterData, который может успешно фильтровать по полу (мужской или женский), но не может получить его также для фильтрации по стране (в пределах объекта местоположения) или навыкам (в массиве навыков). ). Мой текущий метод filterData проходит только одну итерацию для каждого пользователя, но я попытался использовать циклы For и forEach, чтобы попытаться go выполнить каждый из критериев фильтра («Испания», «Оптика»), но он просто не работает , Я получаю только пол.

Я думаю, что у меня есть две проблемы: 1) каким-то образом передать в коде, что в некоторых случаях «ключ» элемента будет не значением, а объектом или массивом, который также должен быть найден внутри, и 2) создание своего рода циклического поведения, которое будет go проходить через каждый из критериев фильтра, вместо остановки после первого (пол).

Это, очевидно, сейчас у меня над головой, так что любые советы или предложения будут оценены, большое спасибо! И вот весь код, с которым я работал, включая мой метод filterData.

var filtering = {
  filter: {
    gender: ["female"],
    location: {
      country: ["Spain"],
    },
    skills: ["optics"],
  },

  users: [
    {
      gender: "male",
      name: "John",
      location: { street: "Clement Street", country: "United States" },
      skills: ["engineering", "underwater"],
    },

    {
      gender: "female",
      name: "Mary",
      location: { street: "5th Avenue", country: "Spain" },
      skills: ["confidence", "optics"],
    },

    {
      gender: "male",
      name: "David",
      location: { street: "Vermont Ave", country: "France" },
      skills: ["cards", "metalurgy", "confidence"],
    },

    {
      gender: "female",
      name: "Rachel",
      location: { street: "Vermont Ave", country: "France" },
      skills: ["disguise", "electrical"],
    },

    {
      gender: "female",
      name: "Muriel",
      location: { street: "Vermont Ave", country: "Germany" },
      skills: ["flight", "surveillance"],
    },
  ],

  filterData: (filter) => {
    const filteredData = filtering.users.filter((item) => {
      for (let key in filter) {
        if (!filter[key].includes(item[key])) {
          return false;
        }
        return true;
      }
    });
    console.log(filteredData);
  },
};

filtering.filterData(filtering.filter);

Ответы [ 2 ]

1 голос
/ 01 мая 2020

Существует изящный трюк с именем recursion, который вызывает саму функцию.

Обновлены следующие коды: checkUser и filterData

var filtering = {
  filter: {
    gender: ["female"],
    location: {
      country: ["Spain"],
    },
    skills: ["optics"],
  },

  users: [
    {
      gender: "male",
      name: "John",
      location: { street: "Clement Street", country: "United States" },
      skills: ["engineering", "underwater"],
    },

    {
      gender: "female",
      name: "Mary",
      location: { street: "5th Avenue", country: "Spain" },
      skills: ["confidence", "optics"],
    },

    {
      gender: "male",
      name: "David",
      location: { street: "Vermont Ave", country: "France" },
      skills: ["cards", "metalurgy", "confidence"],
    },

    {
      gender: "female",
      name: "Rachel",
      location: { street: "Vermont Ave", country: "France" },
      skills: ["disguise", "electrical"],
    },

    {
      gender: "female",
      name: "Muriel",
      location: { street: "Vermont Ave", country: "Germany" },
      skills: ["flight", "surveillance"],
    },
  ],
  
  checkUser (filter, to_check) {
    if (Array.isArray(filter))
    {
      return Array.isArray(to_check)
        ? filter.some(val => to_check.includes(val)) // if what we're checking is an array
        : filter.includes(to_check); // otherwise it's a singular value
    }
    else
    {
      const all_checks = []; // this is to save every return value from the recursive function
      for (let key in filter) // going through each key in the filter
      {
        const checked = this.checkUser(filter[key], to_check[key]) // passing two values, which will be compared with each other
        all_checks.push(checked) // pushing the checked result
      }
      
      return all_checks.every(val => val) // checking that it passes the filter by ensuring every value is true
    }
  },

  filterData () {
    let filter = this.filter
    return this.users.filter(user => this.checkUser(filter, user))
  },
};

// filtering.filterData(filtering.filter);

// filtering.checkUser(filtering.filter, filtering.users[0])
const result = filtering.filterData()
console.log(result)
0 голосов
/ 01 мая 2020

Бит сложной структуры данных, вы должны очистить. Тем не менее, решено, что ожидалось.

const mergeFilter = (item, [key, value]) => {
  let val = Array.isArray(item[key]) ? item[key] : [item[key]];
  let m = value[0];
  if (typeof value === "object" && !Array.isArray(value)) {
    const k2 = Object.keys(value);
    val = item[key][k2];
    m = value[k2][0];
  }
  return val.includes(m);
};
const filterData = (users, filter) => {
  const filters = Object.entries(filter);
  const result = users.reduce((arr, item) => {
    let found = filters.every(mergeFilter.bind(null, item));
    if (found) arr.push(item);
    return arr;
  }, []);
  return result;
};

var filtering = {"filter":{"gender":["female"],"location":{"country":["Spain"]},"skills":["optics"]},"users":[{"gender":"male","name":"John","location":{"street":"Clement Street","country":"United States"},"skills":["engineering","underwater"]},{"gender":"female","name":"Mary","location":{"street":"5th Avenue","country":"Spain"},"skills":["confidence","optics"]},{"gender":"male","name":"David","location":{"street":"Vermont Ave","country":"France"},"skills":["cards","metalurgy","confidence"]},{"gender":"female","name":"Rachel","location":{"street":"Vermont Ave","country":"France"},"skills":["disguise","electrical"]},{"gender":"female","name":"Muriel","location":{"street":"Vermont Ave","country":"Germany"},"skills":["flight","surveillance"]}]}

const result = filterData(filtering.users, filtering.filter);
console.log(result)
...