2016-12-14 5 views
0

Рассмотрим следующий пример:Lodash: фильтровать вложенный объект по нескольким свойствам

var products = { 
    "Products": [{ 
     "Title": "A", 
     "Categories": [{ 
      "Name": "Type", 
      "Properties": ["Type 1", "Type 2", "Type 3"] 
     }, { 
      "Name": "Market", 
      "Properties": ["Market 1", "Market 2", "Market 3", "Market 4"] 
     }, { 
      "Name": "Technology", 
      "Properties": ["Tech 1", "Tech 2"] 
     }] 
    }, { 
     "Title": "B", 
     "Categories": [{ 
      "Name": "Type", 
      "Properties": ["Type 1", "Type 3"] 
     }, { 
      "Name": "Market", 
      "Properties": "Market 1" 
     }, { 
      "Name": "Technology", 
      "Properties": ["Tech 1", "Tech 3"] 
     }] 
    }, { 
     "Title": "C", 
     "Categories": [{ 
      "Name": "Type", 
      "Properties": ["Type 1", "Type 2", "Type 3"] 
     }, { 
      "Name": "Market", 
      "Properties": ["Market 2", "Market 3"] 
     }, { 
      "Name": "Technology", 
      "Properties": ["Tech 2", "Tech 3"] 
     }] 
    }] 
} 

Я пытаюсь фильтровать продукты по своим свойствам так считают, что я использую массив, чтобы следить за выбранными моих фильтров:

var filters = ['Type 3', 'Tech 1']; 

с помощью этих фильтров я хотел бы вернуть продукт а и продукт Б.

настоящее время у меня это:

var flattenedArray = _.chain(products).map('Categories').flatten().value(); 
var result= _.some(flattenedArray , ['Properties', 'Tech 1']); 

Но я зациклился на том, как объединить свойства для комбинированного поиска.

+0

Ваши фильтры всегда относятся к 'Properties'? –

+0

Да, это всегда так. –

ответ

1

Используйте _.filter() для повторной обработки продуктов. Для каждого продукта объедините список свойств с помощью _.flatMap() и используйте _.intersection() и _.size(), чтобы найти количество фильтров, существующих в категориях. Сравните это с исходным количеством фильтров и ответом на результат сравнения.

var products = {"Products":[{"Title":"A","Categories":[{"Name":"Type","Properties":["Type 1","Type 2","Type 3"]},{"Name":"Market","Properties":["Market 1","Market 2","Market 3","Market 4"]},{"Name":"Technology","Properties":["Tech 1","Tech 2"]}]},{"Title":"B","Categories":[{"Name":"Type","Properties":["Type 1","Type 3"]},{"Name":"Market","Properties":"Market 1"},{"Name":"Technology","Properties":["Tech 1","Tech 3"]}]},{"Title":"C","Categories":[{"Name":"Type","Properties":["Type 1","Type 2","Type 3"]},{"Name":"Market","Properties":["Market 2","Market 3"]},{"Name":"Technology","Properties":["Tech 2","Tech 3"]}]}]}; 
 

 
var filters = ['Type 3', 'Tech 1']; 
 

 
var result = _.filter(products.Products, function(product) { 
 
    return filters.length === _(product.Categories) 
 
     .flatMap('Properties') 
 
     .intersection(filters) 
 
     .size(); 
 
}); 
 

 
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

+0

Все свойства в фильтрах должны быть на изделии. Итак, «Тип 3 появляется в C», но «Технология 1» - нет. В моем примере продукт A + B должен быть возвращен, потому что у обоих у них есть «Тип 3» и «Технология 1». –

0

Если я понимаю вас вопрос правильно, этот код может помочь:

_.filter(
    products.Products, 
    product => _.difference(
     filters, 
     _.chain(product.Categories).map(category => category.Properties).flatten().value() 
    ).length === 0 
); 

Он вычисляет объединение всех свойств для каждого продукта:

_.chain(product.Categories).map(category => category.Properties).flatten().value() 

И затем проверяет, содержит ли он все filters элементов массива, используя метод _.difference.

Надеюсь, это поможет.

0

другой фантазии путь через _.conforms

var res = _.filter(
    products.Products, 
    _.conforms({'Categories': function(categories) { 
     return _.chain(categories) 
      .flatMap('Properties') // flat arrays 
      .uniq() // remove dublicates 
      .keyBy() // transform to objects with Properties keys 
      .at(filters) // get objects values by filters 
      .compact() // remove undefineds 
      .size() // get size 
      .eq(filters.length) // compare to filters size 
      .value(); 
    } 
})) 

 Смежные вопросы

  • Нет связанных вопросов^_^