Is there a way to streamline this function call that appears to be redundantly repeating the same actions?

I have developed a function to search for blog posts, prioritizing titles over excerpts and excerpts over content when added to the containsQuery array. While the code seems to be working well, I have noticed that there is a lot of redundant code. How can I streamline this process?

const findArticles = (posts: any[], query: string) => {
    const containsQuery: any[] = []
    let words
    let i: number

    if (query.includes(' ')) {
      words = query.toLowerCase().split(' ')
    }

    const findArticle = (multipleWords:boolean, posts: any[], query:string, searchedParam:string, words:string[] = [],) => {
      if (multipleWords === false) {
        for (i = 0; i < posts.length; i++) {
          if (posts[i][`${searchedParam}`].toLowerCase().includes(query.toLowerCase())) {
            containsQuery.push(posts[i])
          }
        }
      } else {
        for (i = 0; i < posts.length; i++) {
          if(words.every(q => posts[i][`${searchedParam}`].toLowerCase().includes(q))) {
            containsQuery.push(posts[i])
          }
        }
      }
     
    }

    if (words) {
      findArticle(true,  posts, query, 'title', words,)
     } else {
      findArticle(false, posts, query, 'title')
     }

     if (words) {
      findArticle(true,  posts, query, 'excerpt', words,)
     } else {
      findArticle(false, posts, query, 'excerpt')
     }

     if (words) {
      findArticle(true,  posts, query, 'content', words,)
     } else {
      findArticle(false, posts, query, 'content')
     }

    const oneOfKind = Array.from(new Set(containsQuery.map(article => article.id))).map(id => {
      return containsQuery.find(a => a.id === id)
    })
    
    return oneOfKind
  }

To avoid duplicates and improve efficiency, I attempted to create a copy of the posts using my own const copyOfPosts = posts and then modify it, but this caused some issues in the code. The current code structure appears to be the most effective way to achieve the desired outcome. Any suggestions for improvement are greatly appreciated.

if (posts[i][`${searchedParam}`].toLowerCase().includes(query.toLowerCase())) {
            containsQuery.push(posts[i])
            copyOfPosts.splice(i, 1)
          }

Answer №1

Here:

const findArticle = (multipleWords:boolean, posts: any[], query:string, searchedParam:string, words:string[]) => {
    const containsQuery: any[] = []
    if (multipleWords === false) {
        for (let i = 0; i < posts.length; i++) {
            if (posts[i][`${searchedParam}`].toLowerCase().includes(query.toLowerCase())) {
                containsQuery.push(posts[i])
            }
        }
    } else {
        for (let i = 0; i < posts.length; i++) {
            if(words.every(q => posts[i][`${searchedParam}`].toLowerCase().includes(q))) {
                containsQuery.push(posts[i])
            }
        }
    }
    return containsQuery
}

const findArticles = (posts: any[], query: string) => {

    let words = query.includes(' ') ? query.toLocaleLowerCase().split(' ') : [] 

    const containsQuery = findArticle(true, posts, query, 'title', words)

    containsQuery.push(...findArticle(true, posts, query, 'excerpt', words))

    containsQuery.push(...findArticle(true, posts, query, 'content', words))

    const oneOfKind = Array.from(new Set(containsQuery.map(article => article.id))).map(id => {
        return containsQuery.find(a => a.id === id)
    })
    
    return oneOfKind
}

I am planning to optimize the findArticle function in my own way.

const findArticle = (multipleWords:boolean, posts: any[], query:string, searchedParam:string, words:string[]) => {
    const containsQuery: any[] = []
    if (multipleWords === false) {
        for (let i = 0; i < posts.length; i++) {
            if (posts[i][`${searchedParam}`].toLowerCase().includes(query.toLowerCase())) {
                containsQuery.push(posts[i])
            }
        }

        return containsQuery
    } 
    
    for (let i = 0; i < posts.length; i++) {
        if(words.every(q => posts[i][`${searchedParam}`].toLowerCase().includes(q))) {
            containsQuery.push(posts[i])
        }
    }
    return containsQuery
}

This approach avoids using an excessive else statement, although some may argue about having two return statements.

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

When attempting to pass data to a modal, an error occurs due to props being undefined. This results in a TypeError with the message "Cannot

I'm working on a product listing feature where each item displays some information along with a "more details" button. When the button is clicked, a modal window opens to show additional details of the specific product (using props to pass data betwee ...

Is there a way to turn off step navigation in bootstrap?

Displayed below is a visual representation of the bootstrap step navigation component. Presently, there is an unseen 'next' button located at the bottom of the page. When this 'next' button is pressed, it transitions from 'step-1 ...

Is it possible to select multiple drop-down lists on a webpage using Python and Selenium?

I am encountering an issue while attempting to click on multiple dropdown lists within a page. I continuously receive an error message stating that my list object does not have an attribute 'tag_name'. Here is my code snippet: def click_follow_ ...

Use a dropdown menu to update the selected value

Issue with displaying drop down values in the second list, despite trying various solutions. When a user selects a country, the corresponding state should be populated from the database into the second drop-down. Any assistance would be greatly appreciated ...

Binding an event to an Angular 2 component directly within its selector code

Looking at my Angular 2 component: import { Component, ElementRef, Renderer } from '@angular/core';; @Component({ selector: 'my-button', templateUrl: 'button.html' }) export class ButtonComponent { private text: string ...

Encountering a type error with gatsby-plugin-dark-mode in a Typescript Gatsby setup

Issue with Layout warning in index.tsx when hovering: (alias) const Layout: ({ children }: Props) => JSX.Element import Layout Type '{ children: Element[]; }' is missing the following properties from type 'Props': theme, >toggle ...

The function estimatedDocumentCount() actually returns an object rather than a numerical value

I am currently working on a feature in my web application where I want to display the number of documents stored in my MongoDB database whenever a user visits the homepage. To achieve this, I have outlined the implementation process in the following diagra ...

Resolving Unrecognized Vue Variable in PhpStorm

I'm encountering an issue with my Vue script in PhpStorm. Despite setting the variable redirect_to, I am getting an Unresolved variable syntax error during debugging. Please refer to the image below for further information. How can I resolve this prob ...

Issues with aligning center vertically and horizontally using flexbox are causing unexpected behavior

Understanding the basic concepts of centering a flex container using justify-content:center and align-items: center, I am facing an alignment issue with my box. Can anyone help me with this? This is what I have attempted so far: <template> <di ...

Changing the CSS property of a single table cell's innerHTML

I have a question that may seem silly, but I'm going to ask it anyway. Currently, I am iterating through a list of strings that follow the format "1H 20MIN" and adding them to table cells using the innerHTML property like so: for (i = 0; i < list ...

What is the best way to deactivate the first two columns of the header in Vue?

I am attempting to deactivate the draggable function for the first 2 columns. I have tried using options in the draggable plugin. :options="{disabled : 'Subject'}" However, this disables the draggable functionality for all headers. < ...

What is the best way to remove multiple IDs from req.params using Sequelize?

Is there a way to handle req.params that contain multiple IDs? I need to search for and delete these multiple IDs. Here is the code snippet: const ids = req.params; const masterFunders = await masterFunder.findOne({ where: { id: ids ...

What is the best way to transition all elements down while sliding a header up or down?

Is it possible to bring down the entire page when hovering over a header element using CSS, ensuring that the header overlaps nothing else on the page? If so, how can this be achieved? See an example of the header in action here: Thank you! ...

Click on the nearest Details element to reveal its content

Is there a way to create a button that can open the nearest details element (located above the button) without relying on an ID? I've experimented with different versions of the code below and scoured through various discussions, but I haven't be ...

The JavaScript setTimeout function not triggering repetitively for 10 instances

I'm facing an issue with a JavaScript/jQuery function that is designed to call itself multiple times if there is no available data. This is determined by making a web service call. However, the logging inside the web service indicates that it is only ...

Tips for dynamically updating an input within a shadow DOM using code?

Snippet: https://jsfiddle.net/5zrwdjy7/2/ I'm currently working on automating keystrokes with a script within Cypress, however, the target website I am dealing with utilizes web components as inputs. These input elements are nested inside what is kno ...

In JavaScript, the addition and subtraction buttons may become disabled after nested lists are used

Recently, I embarked on a project to enhance the functionality of restaurant table items and implement value-saving features. Initially, everything worked smoothly with one item list. However, upon introducing a second list and attempting to manipulate it ...

Exploring the data types of dictionary elements in TypeScript

I have a model structured like this: class Model { from: number; values: { [id: string]: number }; originalValues: { [id: string]: number }; } After that, I initialize an array of models: I am trying to compare the values with the o ...

JavaScript throws an error when attempting to access an object's methods and attributes

Within my Angular.js module, I have defined an object like this: $scope.Stack = function () { this.top = null; this.size = 0; }; However, when I try to use the push method of this object, I encounter an error stating undefined: ...

TypeError: describe is not a function in the Mocha testing framework

Encountering an issue with mocha-typescript throwing an error indicating that describe is not defined. TypeError: mocha_typescript_1.describe is not a function at DatabaseTest.WrongPath (test/database_test.ts:21:9) at Context.<anonymous> ...