使用Javascript forEach和indexOf

时间:2017-12-13 11:17:45

标签: javascript arrays json

我有JSON格式的数据,我需要在其中执行搜索。有不同的标签可用,当我点击它们时,它会搜索JSON并返回包含这些标签的项目。为此,我使用的是js函数。它第一次正常工作,但是当我在函数中推送第二个过滤器时,它会返回错误的数据。

可用的过滤器是:

装订

  • 平装
  • 精装
  • 有声书
  • 盒装套装

分类

  • Classic Rock
  • 流行音乐
  • Pop Rock
  • Electro Pop
  • Soft Rock

语言

  • 德国

作者

  • 男/女

这是我正在使用的JSON和代码:

var m = {
      "Books": [{
          "title": "Book 1",
          "binding": "paperback",
          "category": "pop",
          "language": "english",
          "author": "male"
        },
        {
          "title": "Book 2",
          "binding": "hardcover",
          "category": "pop rock,electro pop",
          "language": "french",
          "author": "female"
        },
        {
          "title": "Book 3",
          "binding": "audiobook",
          "category": "soft rock",
          "language": "german",
          "author": "male,female"
        },
        {
          "title": "Book 4",
          "binding": "boxed set",
          "category": "rock,classic rock",
          "language": "english",
          "author": "female,male"
        },
        {
          "title": "Book 5",
          "binding": "paperback",
          "category": "electro pop,rock,classic rock",
          "language": "french",
          "author": "male/female"
        },
        {
          "title": "Book 6",
          "binding": "paperback",
          "category": "rock",
          "language": "french",
          "author": "male"
        }
      ]
    }


    // a function which accepts key which is one of binding,category,language,author.
    // the array will be filtered on this key
    function getFilteredElement(key, value) {
        var bookFilter = [];
        m.Books.forEach(function(item){
           var getFilterField = item[key];
           // since the value is a string, so splitting it and creating an array
           var keyArray = item[key].split(',');
           // now checking if the passed value has a presence in the  above array
           if (keyArray.indexOf(value) !== -1) {
               // if present pushed the book name
               bookFilter.push(item.title);
           }
       });
        // returning the array of books
        return bookFilter;
    }

    console.log(getFilteredElement('category', 'rock'))

例如当我按category = rock时,它会返回Book 4, Book 5 and Book 6,但如果我按category = rocklanguage = french,则返回的结果应该只是{ {1}}但它没有返回正确的结果。

有人可以帮忙。

3 个答案:

答案 0 :(得分:4)

您可以使用filters的对象,并使用键搜索键,并将值作为字符串的精确值。

分割并检查带逗号的属性。

function getBooks(filters) {
    return array.Books.filter(function (o) {
        return Object.keys(filters).every(function (k) {
            return o[k].split(',').some(function (v) {
                return v === filters[k];
            });
        });
    });
    //.map(function (o) {
    //    return o.title;
    //});
}

var array = { Books: [{ title: "Book 1", binding: "paperback", category: "pop", language: "english", author: "male" }, { title: "Book 2", binding: "hardcover", category: "pop rock,electro pop", language: "french", author: "female" }, { title: "Book 3", binding: "audiobook", category: "soft rock", language: "german", author: "male,female" }, { title: "Book 4", binding: "boxed set", category: "rock,classic rock", language: "english", author: "female,male" }, { title: "Book 5", binding: "paperback", category: "electro pop,rock,classic rock", language: "french", author: "male/female" }, { title: "Book 6", binding: "paperback", category: "rock", language: "french", author: "male" }] };

console.log(getBooks({ category: 'rock' }));
console.log(getBooks({ category: 'rock', language: 'french' }));
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:2)

使用可以利用Array.prototype.filter()Array.prototype.reduce()String.prototype.includes()来创建这样的过滤系统,其中array filterskey组成可以逐步添加value个对,以优化array books

请参阅下面的实例。

// Books.
const books = [
  {
    "title": "Book 1",
    "binding": "paperback",
    "category": "pop",
    "language": "english",
    "author": "male"
  },
  {
    "title": "Book 2",
    "binding": "hardcover",
    "category": "pop rock,electro pop",
    "language": "french",
    "author": "female"
  },
  {
    "title": "Book 3",
    "binding": "audiobook",
    "category": "soft rock",
    "language": "german",
    "author": "male,female"
  },
  {
    "title": "Book 4",
    "binding": "boxed set",
    "category": "rock,classic rock",
    "language": "english",
    "author": "female,male"
  },
  {
    "title": "Book 5",
    "binding": "paperback",
    "category": "electro pop,rock,classic rock",
    "language": "french",
    "author": "male/female"
  },
  {
    "title": "Book 6",
    "binding": "paperback",
    "category": "rock",
    "language": "french",
    "author": "male"
  }
]

// Query.
const query = (books, filters) => {

  // filters = [{key: 'category', value: 'string'}..]

  return books.filter((book) => {

    // Found?
    return filters.reduce((found, filter) => {
      if (!(book[filter.key].includes(filter.value))) return false
      return found
    }, true)

  })

}

// Log.
console.log('Category = Rock', query(books, [{key: 'category', value: 'rock'}]))
console.log('Category = Rock + Language = French', query(books, [{key: 'language', value: 'french'}]))

console.log('Paperback', query(books, [{key: 'binding', value: 'paperback'}])) // Paperback.
console.log('Paperback + Male', query(books, [{key: 'binding', value: 'paperback'}, {key: 'author', value: 'male'}])) // Paperback + Male.
console.log('Paperback + Male + Pop', query(books, [{key: 'binding', value: 'paperback'}, {key: 'author', value: 'male'}, {key: 'category', value: 'pop'}])) // Paperback + Male + Pop.

答案 2 :(得分:0)

这种方法可以解决您的问题:

function applyFilters(books, filters) {
    for(let filter of filters) {
        var key = filter[0];
        var value = filter[1];
        books = getFilteredElement(books, key, value);
    }

    return books.map(book => book.title);
}

// a function which accepts key which is one of binding,category,language,author.
// the array will be filtered on this key
function getFilteredElement(books, key, value) {
    var bookFilter = [];
    books.forEach(function(item){
       var getFilterField = item[key];
       // since the value is a string, so splitting it and creating an array
       var keyArray = item[key].split(',');
       // now checking if the passed value has a presence in the  above array
       if (keyArray.indexOf(value) !== -1) {
           // if present pushed the book name
           bookFilter.push(item);
       }
   });
    // returning the array of books
    return bookFilter;
}

var filtersToApply = [["category", "rock"], ["language", "french"]];
var bookFilter = applyFilters(m.Books, filtersToApply);
console.log(bookFilter);