Is there a way to obtain a non-matching string in JavaScript?

I have an array of bookings and need to search for a specific value inside the array using searchValue.

In this case, I need to check the booking id field. If the booking id matches the searchValue, then I need to push that object into the result array.

Here's an example of the result array:

  1. Result array example:

    let searchValue = "12,13,15"

Result:

[{ name:"user 3", bookingid:12, product: "ui" },
    { name:"user 4", bookingid:13, product: "ef" }]

Expected Output:

Since 12 and 13 are matched in the booking array, the remaining value in the searchValue is "15". Can someone please provide guidance on how to handle this?

let bookingArr = [
    { name:"user 1", bookingid:10, product: "ab" },
    { name:"user 1", bookingid:10, product: "cd" },

    { name:"user 2", bookingid:11, product: "ui" },
    { name:"user 1", bookingid:10, product: "ef" },

    { name:"user 3", bookingid:12, product: "ui" },
    { name:"user 4", bookingid:13, product: "ef" },
];
let searchValue = "12,13,15";
let set = new Set(searchValue.split(",").map(Number)); // for faster lookup
let res = bookingArr.filter(x => set.has(x.bookingid));
console.log(res);

// how can i get not matched searchValue 
// expected result notmatchedsearchValue ="15"

Check out the demo here

Answer №1

The original poster was close to the solution. To remove each array item's bookingid number-value from the previously generated set, one must use the delete function. Afterwards, creating an array from the modified set and joining its items/values will result in the final string-value output.

The OP's code with slight modifications ...

let bookingArr = [
    { name:"user 1", bookingid:10, product: "ab" },
    { name:"user 1", bookingid:10, product: "cd" },

    { name:"user 2", bookingid:11, product: "ui" },
    { name:"user 1", bookingid:10, product: "ef" },

    { name:"user 3", bookingid:12, product: "ui" },
    { name:"user 4", bookingid:13, product: "ef" },
];
let searchValue = '12,13,15';

let set = new Set(searchValue.split(',').map(Number)); // for faster lookup

bookingArr.forEach(item => set.delete(item.bookingid));

let notmatchedSearchValue = Array.from(set).join(',');

console.log({ searchValue, notmatchedSearchValue });
// expected result notmatchedsearchValue = '15'
.as-console-wrapper { min-height: 100%!important; top: 0; }

A more versatile approach would involve a reducer function that includes a filter-process independent of a specific array item property name. This reducer is capable of both filtering array items based on a custom property name (key) and providing the final string-value of missing (non-matching) values ... something along the lines of ...

function collectMatchingItemAndMissingValue(collector, item) {
  const { key, searchValues, missingValues, matchingItems } = collector;
  const value = item[key];

  if (searchValues.has(value)) {

    matchingItems.push(item);
    missingValues.delete(value);    
  }
  return collector;
}

function getMatchingItemsAndMissingValues(arr, key, searchValues, castValue) {
  searchValues = new Set(
    searchValues.split(',').map(castValue)
  );
  const {
    missingValues,
    matchingItems,
  } = arr.reduce(collectMatchingItemAndMissingValue, {
    key,
    searchValues,
    missingValues: new Set([...searchValues]),
    matchingItems: [],
  });
  return {
    matchingItems,
    missingValues: [...missingValues].join(', '),
  };
}

const bookingArr = [
  { name:"user 1", bookingid:10, product: "ab" },
  { name:"user 1", bookingid:10, product: "cd" },
  { name:"user 2", bookingid:11, product: "ui" },
  { name:"user 1", bookingid:10, product: "ef" },
  { name:"user 3", bookingid:12, product: "ui" },
  { name:"user 4", bookingid:13, product: "ef" },
];
const searchValues = '12, 13, 15';
const castValue = str => Number(str.trim());
const {

  matchingItems,
  missingValues,

} = getMatchingItemsAndMissingValues(bookingArr, 'bookingid', searchValues, castValue);

console.log({ matchingItems, missingValues, searchValues });

console.log({
  ...getMatchingItemsAndMissingValues(
    bookingArr,
    'product',
    'xy, ui, mn, qr, ef',
    str => str.trim(),
  ),
  searchValues: 'xy, ui, mn, qr, ef'
});
.as-console-wrapper { min-height: 100%!important; top: 0; }

Answer №2

This scenario presents a different challenge compared to your previous inquiry. In this case, it is necessary to create a Set from the elements in the bookingArr array rather than from the searchVal.

let bookingArr = [
  { name: "user 1", bookingid: 10, product: "ab" },
  { name: "user 1", bookingid: 10, product: "cd" },

  { name: "user 2", bookingid: 11, product: "ui" },
  { name: "user 1", bookingid: 10, product: "ef" },

  { name: "user 3", bookingid: 12, product: "ui" },
  { name: "user 4", bookingid: 13, product: "ef" },
];

let searchValue = "12,13,15";
let set = new Set(bookingArr.map((b) => b.bookingid));
let res = searchValue
  .split(",")
  .map(Number)
  .filter((s) => !set.has(s))
  .join();
console.log(res);

Answer №3

Here is a possible solution to your problem:

for (let item of items) {
    list.delete(item.id);
}

Afterwards, the list will only contain the items that were not deleted.

If you wish to keep the original values in the list, you can create a copy of the list using let copyList = new Set(list);, and then operate on copyList instead of list in the loop.

For a more concise approach, you can use the following one-liner, inspired by @Barmar:

[...list].filter(x => !items.some(y => y.id == x)).join(",");

Answer №4

If you're open to creating a shallow copy of the new set as an array, we can utilize the array some() method along with negation ! to identify any IDs from that set which are not present in bookingArr.

let bookingArr = [
    { name:"user 1", bookingid:10, product: "ab" },
    { name:"user 1", bookingid:10, product: "cd" },

    { name:"user 2", bookingid:11, product: "ui" },
    { name:"user 1", bookingid:10, product: "ef" },

    { name:"user 3", bookingid:12, product: "ui" },
    { name:"user 4", bookingid:13, product: "ef" },
];
let searchValue = "12,13,15";
let set = new Set(searchValue.split(",").map(Number)); // for faster lookup
let res = bookingArr.filter(x => set.has(x.bookingid));
// console.log(res);
let notMatchedSearchValues = [...set].filter(y => !bookingArr.some(x => y === x.bookingid));

notMatchedSearchValues.forEach(id => console.log(`notMatchedSearchValue: ${id}`));

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

How to Fix Items Being Pushed Down by 'Particleground' Jquery Plugin Due to Z-Index and Positioning

I'm grappling with understanding z-index and positioning, despite reading various questions and articles on the topic. Currently, I'm attempting to incorporate a Jquery Plugin called 'Particleground': https://github.com/jnicol/particle ...

The project is not being recognized by 'webpack' when running within it

Every time I attempt to execute 'webpack' in my project, the command line shows me this error message: 'webpack' is not recognized as an internal or external command, operable program or batch file. I have installed webpack using th ...

What's the best way to make a popup link in my situation?

I'm attempting to use Angular to open a popup window in my situation. Here's what I've got: <a ng-href = "window.open('{{videoLink}}')" >open a video</a> When I try this, I get a 'Not found' error in the br ...

`I am unable to insert an image into PrimeReact`

I am struggling to integrate images into the dashboard using primereact. Despite placing my photo folder in the public directory and entering the correct photo path, the image is not displaying on the page. I have attempted numerous methods but have been ...

What is the best way to attach two separate event listeners to a single button?

I'm attempting to have one button trigger two different functions, but I haven't been successful so far. I tried adding the second event listener as indicated by the // part, but it didn't work. The two functions should be executed sequentia ...

What could be causing the issue with lodash throttle not functioning correctly in the useWindowSize custom hook?

I'm attempting to implement a resize event with throttle, but I'm encountering an issue. To troubleshoot, I have tried the following: import {throttle} from 'lodash' export function useWindowSize() { const [windowSize, setWindowSize] ...

What is the method for loading a subcategory based on the category by invoking a jQuery function within the <td> element of a JavaScript function that adds rows dynamically?

Whenever I click the add row button, the category dropdown list successfully loads. However, when I select an option from this category list, the subcategory does not load any list. The Javascript function responsible for adding rows dynamically is as fol ...

Retrieving the passed argument variable and utilizing it as a key in a map

I've been working on a JavaScript project recently and I've encountered a situation where I believe my code could be significantly reduced - up to 50% - if I could access the passed arguments to a function and use them as keys. Since I'm sti ...

What is the best way to convert a string to an integer in JavaScript while still maintaining compatibility with Internet Explorer 11?

Here is the code snippet that I am working with: setCol (param) { // missing forEach on NodeList for IE11 if (window.NodeList && !NodeList.prototype.forEach) { NodeList.prototype.forEach = Array.prototype.forEach; } const a ...

Is there a way to transfer a significant volume of data from one webpage to another without relying on the POST

Currently, I am utilizing a web server framework that exclusively operates with GET requests. Presently, my task involves transferring a substantial volume of data (specifically the text content in a textarea) inputted by users onto another page where it i ...

Content OverFlow: DropDown Menu is not overlapping the content, but rather pushing it downwards

In my webpage, I have a drop-down menu that traditionally pushes the content below it down to make space for its items. However, I want the drop-down to overlap the contents below without affecting their position. I've tried various solutions, such a ...

Interoperability between C's tiny-aes-c library and Javascript's CryptoJS

Utilizing the implementation from tiny-aes-c, take a look at this C code snippet: int main(int argc, char const *argv[]) { uint8_t key[6] = { 's','e','c','r','e','t' }; uint8_t iv[16] = ...

Encountered an issue while attempting to integrate Nebular into my Angular application

As a newcomer to Angular, I decided to try installing Nebular using the command ng add @nebular/theme. However, I encountered an error in the process. Upon entering the command into my terminal, the following error message appeared: ? Which Nebular theme ...

Tips for utilizing a vue.js nested for loop with two arrays using v-for

The issue has been resolved, and both my parent view and child component code are now correct and functioning properly I am using Vue.js with the goal of iterating similarly to a nested for loop to display a matrix table. Initially, I tried to achieve thi ...

Using JavaScript and HTML, showcase the capital city of a country along with its corresponding continent

As a newcomer to this platform, I am excited to share a code snippet that I have created using HTML and JavaScript. The code generates a textbox in an HTML page where users can type the name of a country. Upon inputting the country's name, the code dy ...

Is there a way to smoothly navigate back to the top within a Modal component while using React?

Here is the code snippet for scrolling back to the top of the page. const ScrollToTop = () => { const [showTopButton, setShowTopButton] = useState(false); useEffect(() => { window.addEventListener("scroll", () => { if ( ...

Utilize Redux Toolkit to efficiently share actions across different slices of state

How can I efficiently share common actions across multiple redux state slices? For instance, let's say I have an updateField action that I want to use in various slices other than just the profile slice. Should I import it from an external file for r ...

Verify if the username or phone number is already in use (front end)

Is there a way to verify user or phone existence on the front-end form? I'm using Yup + Formik for all my requirements, and in my backend with Sequelize, I can check if a username or phone number already exists. passport.use( 'register&apos ...

The Viadeo Social Toolbox seems to be encountering technical difficulties at the moment

I attempted to utilize a Viadeo Social Toolbox, specifically the Viadeo Share Button, but it seems to be malfunctioning in certain browsers? I came across some outdated viadeo share URLs like this: http://www.viadeo.com/shareit/share/?url=${url}&title ...

Tips for resizing a larger image to display only a specific portion in CSS (and incorporating JS if needed)

I need to resize an image that measures 1024x1024 and is segmented into 4 quadrants: My goal is to reduce the size of this image so that quadrant 2 is 256x256 while masking out or hiding the remaining 3 quadrants, displaying only the desired section on th ...