2

I would like to search for a string in array of objects and returns objects that matches. Trying to use es6 here.

Please find below code:

// set of keys
const defConfigs = [{
    title: "Id",
    key: "id"
  },
  {
    title: "Tenant",
    key: "tenant"
  },
  {
    title: "Opened",
    key: "opened"
  },
  {
    title: "Title",
    key: "title"
  },
  {
    title: "Status",
    key: "status"
  },
  {
    title: "Priority",
    key: "priority"
  }
];

// items as array of objects
const items = [{
    id: "INC000000004519",
    title: "Follow-up after INC000000004507",
    description: null,
    urgency: "4-Low",
    severity: "4-Minor/Localized"
  },
  {
    id: "INC000000004515",
    title: "network drop:↵Network Element CVU042_Johnstown get unsynchronized↵Network Element CVU043_Redman",
    description: "Client network drop since 08:51 until 09:06, pleas…ork Element CVU045_North_Salem get unsynchronized",
    urgency: "3-Medium",
    severity: "3-Moderate/Limited"
  },
  {
    id: "INC000000004088",
    title: "not able to schedule GPEH in ABC",
    description: "Contact: [email protected]↵+14692669295↵…WCDMA, we are not able to schedule GPEH in ABC. I",
    urgency: "4-Low",
    severity: "4-Minor/Localized"
  },
  {
    id: "INC000000004512",
    title: "SR Updated - P3 - 2018-0427-0305 - xyz TELECOMMUNICATIONS ROMANIA S.R.L - Lost the  mng connect",
    description: null,
    urgency: "4-Low",
    severity: "4-Minor/Localized"
  },
  {
    id: "INC000000004414",
    title: "Acme incident 1 title",
    description: "Acme incident 1 description",
    urgency: "2-High",
    severity: "1-Extensive/Widespread"
  }
];


// trying to search for string in keys defined in defConfigs
items.filter(item =>
  defConfigs.forEach((def) => {
    if (def.key in item) {
      return (item[def.key].toString().toLowerCase().match('low').length > 1);
    }
  }));

// always throws an error Uncaught TypeError: Cannot read property 'length' of null
console.log(items);

Here, there are 3 objects with string "low" and I expect the code to return the first item (where the "title" is "Follow-up after"); but match never returns.

How do I search for a string in array of objects and return those objects as a result ?

4
  • 1
    .match('low').length will throw if no match is found. Also note that def.key in item is false for all of your examples. Commented May 13, 2018 at 18:04
  • You could use a foreach loop and stringify each object is the array. The do a regex match str.match('low'). If it returns true then return that item Commented May 13, 2018 at 18:05
  • Isn't it supposed to return one item? Two items contain low but in urgency category. Commented May 13, 2018 at 18:58
  • yes exactly. 'low' is in urgency category which isn't in defConfig. But string 'low' is there in title in one of the objects. Commented May 13, 2018 at 19:06

5 Answers 5

1

If you look closely you will notice that:

  1. You do not check if .match matched (it returns null on no match; testing for null.length will throw an error)
  2. You are checking match.length > 1... the syntax you are using will return an array with exactly one item or null
  3. You are missing the return statement for .filter
  4. You do not assign the return value of .filter to any variable

Here is what you need to do:

var filteredItems = items.filter(function (item) {
    return defConfigs.some(function (def) {
        return (def.key in item)
            ? item[def.key].toString().toLowerCase().match('low') !== null
            : false;
    });
});
console.log(filteredItems);
Sign up to request clarification or add additional context in comments.

Comments

1

String.prototype.match() function will return null if there are no matches, therefore you need check this case. Next you could use Array.prototype.some() function to verify that at least one item in array is fulfilling your condition. For example:

items.filter(item =>
  // check if at least one key from `defConfigs` on `item` matches 'low'
  defConfigs.some((def) => {
    if (def.key in item) {
      const matched = item[def.key].toString().toLowerCase().match('low')
      // return true if item matched
      return !!matched
   }
   // match not found by default
   return false
}));

Comments

0

String.prototype.match() will return null when no match found. You should strictly compare match result to null if you want it to work.

You should take a look at Array.prototype.filter. It returns a new array and won't modify the reference passed as argument, your original items are safe (for now).

Comments

0

In your if statement, if (def.key in item), it will check if the value of def.key is equal to the name of an attribute in item. To accomplish what you were thinking of doing, see the comments in the code below:

// set of keys
const defConfigs = [{title: "Id", key: "id"},
{title: "Tenant", key: "tenant"},
{title: "Opened", key: "opened"},
{title: "Title", key: "title"},
{title: "Status", key: "status"},
{title: "Priority", key: "priority"}];

// items as array of objects
const items = [{id: "INC000000004519", title: "Follow-up after INC000000004507", description: null, urgency: "4-Low", severity: "4-Minor/Localized"},
{id: "INC000000004515", title: "network drop:↵Network Element CVU042_Johnstown get unsynchronized↵Network Element CVU043_Redman", description: "Client network drop since 08:51 until 09:06, pleas…ork Element CVU045_North_Salem get unsynchronized", urgency: "3-Medium", severity: "3-Moderate/Limited"},
{id: "INC000000004088", title: "not able to schedule GPEH in ABC", description: "Contact: [email protected]↵+14692669295↵…WCDMA, we are not able to schedule GPEH in ABC. I", urgency: "4-Low", severity: "4-Minor/Localized"},
{id: "INC000000004512", title: "SR Updated - P3 - 2018-0427-0305 - xyz TELECOMMUNICATIONS ROMANIA S.R.L - Lost the  mng connect", description: null, urgency: "4-Low", severity: "4-Minor/Localized"},
{id: "INC000000004414", title: "Acme incident 1 title", description: "Acme incident 1 description", urgency: "2-High", severity: "1-Extensive/Widespread"}];


// trying to search for string in keys defined in defConfigs
items.filter(item =>
defConfigs.forEach((def) => {
  //iterate through all attributes in the object
  for(var key in item){
    //check if the attribute exists, if it has the method 'indexOf' (if it's a string), and that it has def.key in the string
    if (item[key] && item[key].indexOf && item[key].indexOf(def.key)!= -1) {
      //match only accepts regular expressions which are signified in JS by enclosing the expression with forward slashes
      return (item[def.key].toString().toLowerCase().match(/low/).length >1);
    }
   }
}));

Comments

0

The word "low" is found only in the urgency attribute and your defConfigs array don't have this field
So after you add it to the array do the following :

let newItems=items.filter(item => {


    let count= defConfigs.reduce((acc, def) => {

        if (def.key in item) {
            let arr = item[def.key].toString().toLowerCase().match(/low/gi)
            return acc + (arr ? 1 : 0);
        }
        else {

            return acc;
        }
    }, 0)

    return count >0
});

console.log(newItems);
  • So first define a new variable for the filtered data newItems
  • Then i used the reduce function to get if there is any match in the whole object
  • lastly used the regular expression /low/gi in the match function

3 Comments

Correct. Tried to modify code but SO doesn't allow.
if my solution helped you solve the problem, please mark it as solved
'low' is in urgency category which isn't in defConfig. But string 'low' is there in title in one of the objects.

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.