Tips for utilizing filters to search through various key values within an array of objects

In my collection of wines, each wine is represented by an object with specific data:

var wines = [
  { _id: '59a740b8aa06e549918b1fda',
    wineryName: 'Some Winery',
    wineName: 'Pinot Noir',
    wineColor: 'Red',
    imageLink: '/img/FortBerensPN.png' },
  { _id: '59a7410aaa06e549918b1fdb',
    wineryName: 'Some Winery',
    wineName: 'Pinot Gris',
    wineColor: 'White',
    imageLink: '/img/FortBerensPG.png' },
  { _id: '59a74125aa06e549918b1fdc',
    wineryName: 'Some Winery',
    wineName: 'Rose',
    wineColor: 'Rose',
    imageLink: '/img/FortBerensRose.png' },
  { _id: '59a74159aa06e549918b1fdd',
    wineryName: 'Some other Winery',
    wineName: 'Rose',
    wineColor: 'Rose',
    imageLink: '/img/FortBerensRose.png' },
  { _id: '59a7417aaa06e549918b1fde',
    wineryName: 'Some other Winery',
    wineName: 'Pinot Gris',
    wineColor: 'White',
    imageLink: '/img/FortBerensPG.png' },
  { _id: '59a8721f4fd43b676a1f5f0d',
    wineryName: 'Some other Winery',
    wineName: 'Pinot Gris',
    wineColor: 'White',
    imageLink: '/img/FortBerensPG.png' },
  { _id: '59a872244fd43b676a1f5f0e',
    wineryName: 'Winery 3',
    wineName: 'Pinot Noir',
    wineColor: 'Red',
    imageLink: '/img/FortBerensPN.png' } ]

I'm trying to search for a wine object in a case-insensitive manner by specifying the key to search in with the following code:

var search = 'Noir'

filteredWines = function () {
  return wines.filter(function(wine){
    return (wine.wineName.toLowerCase().indexOf(search.toLowerCase())>=0;
  });
};

This code snippet returns:

[ { _id: '59a740b8aa06e549918b1fda',
    wineryName: 'Some Winery',
    wineName: 'Pinot Noir',
    wineColor: 'Red',
    imageLink: '/img/FortBerensPN.png' },
  { _id: '59a872244fd43b676a1f5f0e',
    wineryName: 'Winery 3',
    wineName: 'Pinot Noir',
    wineColor: 'Red',
    imageLink: '/img/FortBerensPN.png' } ]

However, searches for var search = 'Winery 3' or var search = 'red' do not yield any results because the search is limited to the wineName key in each object.

Is there a way to expand the search to include all key values, or even better, search multiple specified key values and return an array of matching objects?

Could a solution involve using filter or another method to achieve this, maybe something like:

filteredWines = function () {
  return wines.filter(function(wine){
    return ((wine.wineName.toLowerCase() && wine.wineName.toLowerCase() 
          && wine.wineName.toLowerCase()).indexOf(search.toLowerCase())>=0;
  });
};

Or am I on the wrong track completely?

Any suggestions or insights on a better way to accomplish this within Vue.js 2 would be greatly appreciated!

Answer №1

A more versatile approach would be to create a function that scans through all the properties for a specific string. By iterating through all property values using Object.values() and utilizing some to stop once a match is found:

filteredItems = function (query) {
    var searchTerm = query.toLowerCase();
    return items.filter(item =>
        Object.values(item).some(value => 
            String(value).toLowerCase().includes(searchTerm) 
        )
    );
}

If you prefer to specify the keys to search in:

filteredItems = function (query, keys) {
    var searchTerm = query.toLowerCase();
    return items.filter(item =>
        keys.some(key => 
            String(item[key]).toLowerCase().includes(searchTerm) 
        )
    );
}

Usage example:

filteredItems('Apple', ['fruitName', 'color']);

Answer №2

Another approach is to do it like this:

    In this implementation, the wines array is filtered based on whether any of the properties of each item contain the search value being input. The toLowerCase() method is used to make the comparison case-insensitive.
    this.wines = this.wines.filter((item) => {
                return (item.wineryName.toString().toLowerCase().indexOf(val.toLowerCase()) > -1 ||
                item.wineName.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
                item.wineColor.toLowerCase().indexOf(val.toLowerCase()) > -1);
            })

Answer №3

I was inspired by the solution provided by "trincot" and adapted it for my Angular 5 application:

customFilter(searchTerm, itemList): Observable<IFilteredList> {
  return itemList.filter(item => {
    return Object.values(item).some(val =>
      String(val).includes(searchTerm)
    );
  })
}

Answer №4

Filter functions correctly. My mistake, upon closer inspection of the question. Filter still functions, but the values also need to be filtered.

let wines = [
    {
        _id: '59a740b8aa06e549918b1fda',
        wineryName: 'Some Winery',
        wineName: 'Pinot Noir',
        wineColor: 'Red',
        imageLink: '/img/FortBerensPN.png'
    },
    {
        _id: '59a7410aaa06e549918b1fdb',
        wineryName: 'Some Winery',
        wineName: 'Pinot Gris',
        wineColor: 'White',
        imageLink: '/img/FortBerensPG.png'
    },
    {
        _id: '59a74125aa06e549918b1fdc',
        wineryName: 'Some Winery',
        wineName: 'Rose',
        wineColor: 'Rose',
        imageLink: '/img/FortBerensRose.png'
    },
    {
        _id: '59a74159aa06e549918b1fdd',
        wineryName: 'Some other Winery',
        wineName: 'Rose',
        wineColor: 'Rose',
        imageLink: '/img/FortBerensRose.png'
    },
    {
        _id: '59a7417aaa06e549918b1fde',
        wineryName: 'Some other Winery',
        wineName: 'Pinot Gris',
        wineColor: 'White',
        imageLink: '/img/FortBerensPG.png'
    },
    {
        _id: '59a8721f4fd43b676a1f5f0d',
        wineryName: 'Some other Winery',
        wineName: 'Pinot Gris',
        wineColor: 'White',
        imageLink: '/img/FortBerensPG.png'
    },
    {
        _id: '59a872244fd43b676a1f5f0e',
        wineryName: 'Winery 3',
        wineName: 'Pinot Noir',
        wineColor: 'Red',
        imageLink: '/img/FortBerensPN.png'
    }
];

let search = (val) => wines.filter(w => Object.values(w).filter(v => v.toLowerCase().indexOf(val.toLowerCase()) !== -1).length > 0);

console.log(search('some'));

Answer №5

In my opinion, taking a broader approach might be beneficial:

function filterWinesByKeywords(keys, searchTerm, wines) {

  function extractKeywords(keys, item) {
    let keywords = '';
    keys.forEach(key => {
        keywords += ' ' + item[key];
    });
    return keywords.toLowerCase();
  }

  return wines.filter(wine => {
    const allKeywords = extractKeywords(keys, wine);
    return allKeywords.includes(searchTerm.toLowerCase());
  });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What should you choose between vuex "store" and "data: store" in the Vue() constructor?

Vue documentation recommends using the "data" option in the constructor to maintain global or shared data: Link This approach seems logical and practical. Contrastingly, Vuex documentation initializes the "store" object without specifying a property name ...

Where should the logic for the Redux app be implemented for optimal performance?

My react-redux app features an action-creator that filters a list of objects based on a specified title: export const filterItems = (title) => dispatch => { axios.get(`/api/items/?title=${title}`) .then(res => { dispatch({ ...

Is there a way to transform a JSON array into a dictionary that can store duplicate keys as well?

I've been attempting to convert my JSON array into key/value pairs in a Dictionary, but I keep encountering the issue of receiving null Keys and Values. Error : System.ArgumentNullException: 'Value cannot be null. Parameter name: key' What ...

Guide on creating a Discord bot that can delete its own message in a private message (DM) using Discord.js

Working on my Discord.js Discord bot, I'm exploring the option of having the bot delete its own message from a DM chat. Is it feasible to achieve this and if so, what code should I use? Attempting msg.delete() is throwing an error mentioning that this ...

Swap the text within the curly braces with the div element containing the specified text

I have an input and a textarea. Using Vue, I am currently setting the textarea's text to match what's in the input field. However, now I want to be able to change the color of specific text by typing something like {#123123}text{/#}. At this poin ...

Issues with reactivity are present in certain items within Vue.js cards

Can someone please assist me with this issue that has been causing me trouble for days? I am working on updating the quantity and total price in a checkout card: The parent component: <template> <div> <upsell-checkout-product ...

"Ensuring Security with Stripe Connect: Addressing Content Security Policy Challenges

Despite using meta tags to address it, the error persists and the Iframe remains non-functional. <meta http-equiv="Content-Security-Policy" content=" default-src *; style-src 'self' 'unsafe-inline'; ...

Converting a JSON array into a single JSON object using Powershell

I need assistance converting a JSON array into a single JSON Object. I have provided the output screenshot for reference: https://i.sstatic.net/vT55z.png My desired output is shown in this screenshot: https://i.sstatic.net/rL8Yp.png This is the PowerShel ...

What is the best way to slice the string into segments and organize them within an array?

On my website, there is a text box where users can input a series of numbers in the following format: (118,38,137,15,156,14,157,36,152,49,142,57) I want to know how I can store these numbers in an array as shown below: [118 38 137 15 156 1 ...

Tips for implementing a client-side event when an asp:menu item is clicked

Currently, I'm incorporating the <asp:Menu> control into my website and populating it with data from a table in my Sql Server database using an XML data source. Now, I am looking to implement a client-side event when a user clicks on a menu item ...

Updating cluetip content post webpage loading

I need to update the content within a cluetip after the page has finished loading. Imagine there's a button inside the cluetip and upon clicking it, I want it to disappear. Here is the cluetip setup: $('a.notice_tooltip').cluetip({activa ...

Obtaining an Array through a direct input on the command line

I am having trouble incorporating raw command line arguments in my Node.js application. When I try with simple variables, everything works as expected (node example.js variable) However, when I pass an array as an argument, it does not work properly (n ...

Embed full content in iframe using bootstrap 4

Embedding an iframe of an appointment scheduling frontend on my page has been a challenge. While the width is correct, the height of the frame is too small. Despite attempting various CSS modifications, I have not been able to achieve the desired result. I ...

Vue 2 reloads and displays content upon page load

I am currently using Vue 2.5 and facing an issue where the data is not updating even after fetching API in the created function and calling window.print() in the updated function. Despite all efforts, the page still shows blank content. Created Function c ...

Angular JS does not acknowledge null values

Within my controller, the variable $scope.test is assigned a value from the server. When this value is null, line 1 of the code below prints 'null', however it still enters the else condition. I have attempted to use $scope.test != null and $scop ...

States following form submission in an HTTP request may vary

When attempting to submit a form and receive the results on the same page using AJAX, a JavaScript function is called onsubmit, initiating the AJAX call and including the following code: request=new XMLHttpRequest(); /* set up request here ...

error message: "The CSRF token is either missing or incorrect, please try again."

I implemented window.CSRF_TOKEN = "{{ csrf_token }}" within a script tag in restaurant_detail.html where my react page for posting reviews is rendered. However, I encountered an error. Upon checking in my onSubmit function, I confirmed that the csrf token ...

Retrieve the content of a text field with jQuery

Check out this block of HTML: <div class="sub-middle-column"> <div class="div-header">Grandsire <a "#", class="table-control-focus sub-header-table-focus" id="table-control-focus-t" >abc</a> <ul class="table-controls h ...

Create a JavaScript and jQuery script that will conceal specific div elements when a user clicks on them

Within my navigation div, there exists another div called login. Through the use of JavaScript, I have implemented a functionality that reveals additional divs such as login_name_field, login_pw_field, register_btn, do_login_btn, and hide_login upon clicki ...

Transmit HTML message using the "textarea" tag through email

Whenever I try to send the content of my "textarea" via email, it always ends up being sent as a blank message. How can I fix this issue? Below is my PHP code: <?php $input = json_decode(file_get_contents("php://input"), true); $ToEmail = "<a href ...