Как передать строковый литерал в функцию фильтра в javascript - PullRequest
1 голос
/ 11 апреля 2020

Я хочу передать строковый литерал в функцию фильтра.

результат должен быть

filter = data.filter(o => o.tag.toLowerCase().indexOf(("website").toLowerCase()) != -1 &&
          o.tag.toLowerCase().indexOf(("phone").toLowerCase()) != -1

В настоящее время я делаю

  • Использование а для l oop чтобы получить все теги в массиве
  • сформировать строковый запрос и выполнить фильтр в массиве
  • проблема в том, что когда фильтр пропущен, он возвращает все, смысл строкового литерала в неработающем
for (let i = 0; i < values.length; i++) {
          if (i + 1 >= values.length) {
            query = query.concat(` o.tag.toLowerCase().indexOf(("${values[i]}").toLowerCase()) != -1 `);
          } else {
            query = query.concat(` o.tag.toLowerCase().indexOf(("${values[i]}").toLowerCase()) != -1 && `);
          }

        }
let filter = data.filter(o => `${query}`);
        debugger;


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

data=[{name:"fpl.xlsx",author:"hello",hits:6,date:"2020-01-01",tag:"logo,website"}
,{name:"corporate.pptx",author:"hellob",hits:1,date:"2020-02-01",tag:"logo"},
{name:"index.html",author:"hellob",hits:7,date:"2020-02-02",tag:"logo,abc"}

]

let filter=[];
filter=data.filter(o=>o.tag.indexOf("logo")!=-1 && o.tag.indexOf("abc")!=-1)

console.log(filter);

Ответы [ 2 ]

2 голосов
/ 11 апреля 2020

Если вы хотите убедиться, что все из values соответствуют элементу, который находится в tag, то вы можете использовать Array#every, чтобы сделать это.

const arr1 = ["aardvark", "ant", "alien"];
const arr2 = ["apple", "audi", "bcoccoli"];

const startsWithA = word => word[0] === "a";

console.log(arr1.every(startsWithA));
console.log(arr2.every(startsWithA));

Кроме того, метод String#includes можно использовать вместо .indexOf, поскольку он напрямую возвращает логическое значение.

const word = "applesauce";

console.log(word.includes("apple"));
console.log(word.includes("sauce"));

Итак, мы получаем это:

const data = [{name:"fpl.xlsx",author:"hello",hits:6,date:"2020-01-01",tag:"logo,website"}
,{name:"corporate.pptx",author:"hellob",hits:1,date:"2020-02-01",tag:"logo"},
{name:"index.html",author:"hellob",hits:7,date:"2020-02-02",tag:"logo,abc"}]

const values = ["logo", "abc"];

let result = data
  .filter(
    ({tag}) => values.every(
        value => tag.toLowerCase()
            .includes(value.toLowerCase())
     ) 
  )
  
console.log(result);

Однако, поскольку tag содержит список через запятую, вы можете получить ложные срабатывания:

const tag1 = "foobar";
const tag2 = "foo,bar";

const values = ["foo", "bar"];

console.log(values.every(value => tag1.includes(value)));
console.log(values.every(value => tag2.includes(value)));

Тег может быть словом, состоящим из нескольких других и совпадающих, в то время как вы хотите только полное совпадение. Вы можете использовать String#split для разделения тегов, и вам просто нужно выяснить, перекрываются ли два массива:

const tag1 = "foobar";
const tag2 = "foo,bar";

const values = ["foo", "bar"];

const arrayOfTag1 = tag1.split(",");
const arrayOfTag2 = tag2.split(",");

console.log(values.every(value => arrayOfTag1.includes(value)));
console.log(values.every(value => arrayOfTag2.includes(value)));

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

const data = [{name:"fpl.xlsx",author:"hello",hits:6,date:"2020-01-01",tag:"logo,website"}
,{name:"corporate.pptx",author:"hellob",hits:1,date:"2020-02-01",tag:"logo"},
{name:"index.html",author:"hellob",hits:7,date:"2020-02-02",tag:"logo,abc"}]

const values = ["logo", "abc"];

let result = data
  .filter(
    ({tag}) => {
      const lookupTags = new Set(
        tag
          .split(",")
          .map(x => x.toLowerCase())
      );
    
      return values.every(value => lookupTags.has(value.toLowerCase())
     )
   })
  
console.log(result);
1 голос
/ 11 апреля 2020

Почему вы не можете вставить for в функцию обратного вызова фильтра?

Например:

data = data.filter( o => {
  for ( let i = 0; i < values.length; i++ ) {
    if ( o.tag.toLowerCase().indexOf(values[i].toLowerCase()) == -1 ) {
       return false;
    }
  }
  return true;
} );
...