skip to Main Content

Assume this object:

const data = {
    "text-a": ["Text-1", "Text-2", "Example-3", "Text-4"],
    "text-b": ["Example-1", "Example-2", "Other-Example-3", "Text-1b"]
}

// This object should be updated only with the data that matches the searchInput. 
var filteredData = {} 

// This value changes on user text input.
var searchInput = "tex"  

and need to filter it based on user text input. The filter should be applied to the array values, and when no values match the search input, remove its key as well.

my current non-working implementation looks like this, but I cannot get it working as it returns always ‘undefined:

filteredData = Object.keys(data).forEach((key) => (
    filteredData[key] = data[key].filter((x) => 
   (x.includes(searchInput)))
))

thank you.

3

Answers


  1. Three remarks about your code:

    • The way you use includes performs a case-sensitive search, my suggestion uses a case-insensitive regular expression.
    • The filteredData you construct is an array, but you seem to want an object.
    • You need a check whether an array becomes empty after filtering.
    const data = {
      "text-a": ["Text-1", "Text-2", "Example-3", "Text-4"],
      "text-b": ["Example-1", "Example-2", "Other-Example-3", "Text-1b"]
    };
    const filteredData = {};
    var searchInput = new RegExp("tex", "i"); // case-insensitive
    for (var p in data) {
      var filtered = data[p].filter(text => searchInput.test(text));
      if (filtered.length > 0) filteredData[p] = filtered;
    }
    console.log(filteredData);
    Login or Signup to reply.
  2. Try this code:

    const data = {
        "text-a": ["Text-1", "Text-2", "Example-3", "Text-4"],
        "text-b": ["Example-1", "Example-2", "Other-Example-3", "Text-1b"]
    };
    
    var searchInput = "Tex";
    
    var filteredData = Object.keys(data).reduce((acc, key) => {
        const filteredArray = data[key].filter(x => x.includes(searchInput));
        if (filteredArray.length > 0) {
            acc[key] = filteredArray;
        }
        return acc;
    }, {});
    
    // Convert filteredData to text representation
    var filteredDataText = Object.keys(filteredData).map(key => {
        return `${key}: ${filteredData[key].join(', ')}`;
    }).join('n');
    
    console.log(filteredDataText);
    

    and if you want make case insensitive:

    const data = {
        "text-a": ["Text-1", "Text-2", "Example-3", "Text-4"],
        "text-b": ["Example-1", "Example-2", "Other-Example-3", "Text-1b"]
    };
    
    var searchInput = "Tex";
    
    var filteredData = Object.keys(data).reduce((acc, key) => {
        const filteredArray = data[key].filter(x => x.toLowerCase().includes(searchInput.toLowerCase()));
        if (filteredArray.length > 0) {
            acc[key] = filteredArray;
        }
        return acc;
    }, {});
    
    // Convert filteredData to text representation
    var filteredDataText = Object.keys(filteredData).map(key => {
        return `${key}: ${filteredData[key].join(', ')}`;
    }).join('n');
    
    console.log(filteredDataText);
    
    Login or Signup to reply.
  3. The .forEach() method returns undefined in JavaScript, so assigning the result of that to filteredData is going to make filteredData undefined.

    One way to approach this is to get the entries of your data object ([[key, value], [key2, value2], ...] and then map each of the inner entry arrays (using .map()) to new entries, where each value is a filtered version of your array. Once you’ve transformed each inner entry array by mapping it, you can perform an additional filter to keep only the key-value pairs where your array’s value length is more than 0 (non-empty). You can then convert the transformed array of entries into a new object using Object.fromEntries():

    const data = {
        "text-a": ["Text-1", "Text-2", "Example-3", "Text-4"],
        "text-b": ["Example-1", "Example-2", "Other-Example-3", "Text-1b"]
    };
    
    const searchInput = "tex";
    const filteredData = Object.fromEntries(Object.entries(data).map(([key, value]) => [
      key,
      value.filter(val => val.toLowerCase().includes(searchInput.toLowerCase()))
    ]).filter(([, val]) => val.length > 0));
    
    console.log(filteredData);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search