1

I have two arrays; one with substrings and the other with objects.

I would like to obtain an array of objects where those objects contain any of the substrings in the substrings array.

So far I have tried to use filter and findIndex. Each approach works if a substring is identical. In this case, even indexOf was not working. I am not javascript guy, so probably I am doing something wrong.

Script

  var strings = ['12', 'sv', 'eli', '23', '34'];

  var data = [
    {
      a: 349531284734,
      b: "sv123eippppppeli",
      c: "aaabbbccc"
    },
    {
      a: 1111123333312,
      b: "ccccccccccccs2222",
      c: "aaabbbccc"
    },
    {
      a: 2222234,
      b: "elllllllla",
      c: false
    },
  ];


  // attempt 1

  var results = data.filter(arr =>
    Object.keys(arr).some(key => {
      return String(arr[key]).toLowerCase().includes(strings) // or indexOf
    })
  );


  // attempt 2 with only one data index

  var obj = Object.values(data[0]);
  var results = strings.some(s => obj.includes(s)) // or indexOf or findIndex;

Explanation

In this example with the given substrings, only data[0] is a match because it contains at least on of the substrings in the strings array.

How can I make this work without using a "for loop"?

Thanks

5
  • what is the expected output for the given input? Commented Oct 3, 2019 at 22:45
  • it needs to return matched object. So, if data contains strings from array it needs to return. If substring is ['aa', 'bb'] and object is {a: 1, b: "oo", c: "aabb"} it needs to return that object. Commented Oct 3, 2019 at 22:50
  • developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Though to that effect, String.prototype.includes expects the argument to be another string, not an array of strings Commented Oct 3, 2019 at 22:55
  • @Taplar include should work also, as it is demonstrated by Dacre Denny in answer. Commented Oct 3, 2019 at 22:59
  • @Taplar ah, yes. Sorry. My mistake Commented Oct 3, 2019 at 23:01

1 Answer 1

1

A simple solution that avoids the need for "for-loop" syntax would be to filter() each object of data by a predicate that checks if any value (of the current item being filtered) contains any one of the values of the strings array.

In code, this can be expressed as:

var strings = ['12', 'sv', 'eli', '23', '34'];

var data = [{
    a: 349531284734,
    b: "sv123eippppppeli",
    c: "aaabbbccc"
  },
  {
    a: 1111123333312,
    b: "ccccccccccccs2222",
    c: "aaabbbccc"
  },
  {
    a: 2222234,
    b: "elllllllla",
    c: false
  },
];

// Local helper retruns true if case-insenstive value in strings array
const stringHasValue = (value) => strings
  .some(str => value.toLowerCase().includes(str.toLowerCase()))

// Filter each item in data array by existance of a value containing
// substring in strings array
var result = data.filter((item) => Object.values(item)
  .filter(value => typeof value === 'string')
  .some(stringHasValue, []));

console.log(result);

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

2 Comments

Fantastic. I was close, but not that close. Thanks again.
Only problem with your code is that if i am creating array of substrings on input type and after creation initiating your code, somehow it resets and older values is being ignored. var strings = this.value.toLowerCase().split(' ').filter(Boolean) but thats a bit offtopic i think.

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.