0

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"]
  }]
10
  • so you are matching only size and color? Commented Jun 3, 2021 at 12:25
  • @RajdeepDebnath sorry updated the question. I want to match on each Commented Jun 3, 2021 at 12:40
  • 1
    Why ` size: 7,` item did not exist in the expected result? Commented Jun 3, 2021 at 12:56
  • I see you want to exclude the last object in the array. Does this mean that objects that pass through the filter aren't allowed to contain a different value even though one of the values match? What I mean is, it seems like you're trying to exclude the last object since it contains tennis, even though it contains running. Was this a typo, or was this intentional? Commented Jun 3, 2021 at 13:11
  • 1
    please adjust the wanted result as well. Commented Jun 3, 2021 at 14:02

3 Answers 3

1

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; }

Sign up to request clarification or add additional context in comments.

Comments

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);

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.