简体   繁体   中英

filter objects based on values and arrays as values js

I am trying to create a filter that is working when the object is a single value, but when introducing an array of keywords I am having issues.

My code looks like the following:

 const filter = { colors: ["white"], sizes: [9, 12], brands: ["adidas"], keywords: ["running", "weights"] }; const shoes = [{ brand: "adidas", size: 9, color: "white", keywords: ["running"] }, { brand: "adidas", size: 12, color: "white", keywords: ["weigths"] }, { brand: "nike", size: 7, color: "red", keywords: ["running", "tennis"] } ]; const properties = { colors: 'color', sizes: 'size', brands: 'brand', keywords: 'keywords', } const filters = Object.entries(filter).filter(([, { length }]) => length).map(([k, v]) => [properties[k], v]); const result = shoes.filter(shoe => filters.every(([k, v]) => v.includes(shoe[k]))); console.log('result', result)

The result that I am looking for is

const results = {
    brand: "nike",
    size: 9,
    color: "white",
    keywords: ["running"]
  },
  {
    brand: "adidas",
    size: 12,
    color: "white",
    keywords: ["swimming"]
  }]

By having matching words withou spellin g differences, you could create an array of every value and check against the wanted values.

 const filter = { colors: ["white"], sizes: [9, 12], brands: ["adidas"], keywords: ["running", "weights"] }, shoes = [{ brand: "nike", size: 9, color: "white", keywords: ["running"] }, { brand: "adidas", size: 12, color: "white", keywords: ["weights"] }, { brand: "nike", size: 7, color: "red", keywords: ["running", "tennis"] }], properties = { colors: 'color', sizes: 'size', brands: 'brand', keywords: 'keywords' }, filters = Object.entries(filter).filter(([, { length }]) => length).map(([k, v]) => [properties[k], v]), result = shoes.filter( shoe => filters.every( ([k, v]) => [].concat(shoe[k]).some(value => v.includes(value)) ) ); console.log('result', result);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

My assumption, you are filtering by size , color and keywords not by brand and based on that I produced the code below, but if the assumption is not valid please provide more details

You can use array.filter to filter an array by passing conditions

let result = shoes.filter(f => filter.sizes.includes(f.size) 
                  && filter.colors.includes(f.color) 
                  && filter.keywords.some(k => f.keywords.includes(k))
             )

console.log(result);

The following should take filter out any object that has a value inconsistent with the filters:

const filterObjectArray = (filters, array) => {
  return array.filter(obj => {
  
    // iterate through each key in filters
    for (let i in filters) {
    
      const objVal = obj[properties[i]]
    
      // here, we can use flatMap to "spread" objVal and filters[i] into
      // an array, whether or not objVal is an array
      const combinedValues = [objVal, filters[i]].flatMap(x => x)
      
      // convert the combinedValues into a Set to remove duplicates
      const set = new Set(combinedValues)
      
      // If the size of the set matches the length of combinedValues
      // it means that objVal and filters[i] have no values in common, so we
      // can just return false.
      if (set.size === combinedValues.length) return false
    }
    
    // If we reach here, it means every value in object has been validated by every key/value in filters.
    return true
  })
}

Here's a repl where you can see this code in action: https://replit.com/@isaacsan123/filtering-objects

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM