Extracting specific words from a string query [javaScript] - javascript

I have a string query
const query = '(travel OR explore OR vacation OR trip) NOT (app OR agency) AND flight';
I want to store the words inside "NOT" block in an array.
What could be the most effective approach for this?
Expected result - ["app", "agency"]

We can use match(), twice:
const query = '(travel OR explore OR vacation OR trip) NOT (app OR agency) AND flight';
var terms = query.match(/\bNOT\s*\((.*?)\)/)[1]
.match(/\w+/g)
.filter(x => x !== "OR" && x !== "AND");
console.log(terms);

const query = '(travel OR explore OR vacation OR trip) NOT (app OR agency) AND flight';
function useRegex(input) {
let regex = /\(([a-zA-Z]+( [a-zA-Z]+)+)\) NOT \(([a-zA-Z]+( [a-zA-Z]+)+)\) ([A-Za-z0-9]+( [A-Za-z0-9]+)+)/i;
return input.match(regex);
}
console.log(useRegex(query)[3]);

Step 1: Split the query before and after NOT keyword using query.split('NOT')
-> Here only data after NOT is needed so we can use, query.split('NOT')[1]
Step 2: Use regex rx.exec(res)[1] to get the value in between the paranthesis.
Step 3: Get the values before and after OR.
const query = '(travel OR explore OR vacation OR trip) NOT (app OR agency) AND flight';
const res = query.split('NOT')[1];
const rx = /\(([^)]+)\)/;
const result = rx.exec(res)[1].split(' OR ');
console.log(result);

Related

Remove string from string using regex and return part of removed

I am trying to extract a component name from a string so I can parse the rest with JSON and also return the component name.
Let's say I have a string as follows:
namespace/Slider {"showCaptions":true,"circular":false,"autoPlay":true,"showItemNavigators":true,"showItemNavigatorsOnHover":true,"showIndicators":false,"indicatorsPosition":"bottom","showThumbnails":true,"numVisible":10,"numVisible1536":8,"numVisible1280":6,"numVisible1024":4,"numVisible768":3,"numVisible640":2,"changeItemOnIndicatorHover":false,"images":[{"id":1701,"url":"http://localhost:10019/wp-content/uploads/2022/12/horse.jpeg","alt":"horse alt","caption":"Name some name"},{"id":1699,"url":"http://localhost:10019/wp-content/uploads/2022/12/GPJNews_Mongolia_KK_RidingChild_076_web-920x613-1.jpeg","alt":"","caption":"Name GP"},{"id":1238,"url":"http://localhost:10019/wp-content/uploads/2022/08/test-scaled.jpeg","alt":"","caption":""},{"id":458,"url":"http://localhost:10019/wp-content/uploads/2022/09/news-scaled-1.jpeg","alt":"","caption":"Paswan a mother who..."}]}
I want to remove the "namespace/Slider" part from the string and return the rest so I can JSON.parse it and also want to return "Slider" so the part after namespace as a variable.
EDIT: This is how I was doing it before and it worked until I had a ( in any of the fields eg: "caption":"(Name GP"
const str = `namespace/Slider {"showCaptions":true,"circular":false,"autoPlay":true,"showItemNavigators":true,"showItemNavigatorsOnHover":true,"showIndicators":false,"indicatorsPosition":"bottom","showThumbnails":true,"numVisible":10,"numVisible1536":8,"numVisible1280":6,"numVisible1024":4,"numVisible768":3,"numVisible640":2,"changeItemOnIndicatorHover":false,"images":[{"id":1701,"url":"http://localhost:10019/wp-content/uploads/2022/12/horse.jpeg","alt":"horse alt","caption":"Name some name"},{"id":1699,"url":"http://localhost:10019/wp-content/uploads/2022/12/GPJNews_Mongolia_KK_RidingChild_076_web-920x613-1.jpeg","alt":"","caption":"Name GP"},{"id":1238,"url":"http://localhost:10019/wp-content/uploads/2022/08/test-scaled.jpeg","alt":"","caption":""},{"id":458,"url":"http://localhost:10019/wp-content/uploads/2022/09/news-scaled-1.jpeg","alt":"","caption":"Paswan a mother who..."}]}`;
const component = str
.replace(/\{([^()]|())*\}/gi, '')
.trim()
.split('/')[1];
const obj = str.match(/\{([^()]|())*\}/gi)[0]
console.log(component, obj);
Take the substring starting from the first { character.
let str = 'namespace/Slider {"showCaptions":true,"circular":false,"autoPlay":true,"showItemNavigators":true,"showItemNavigatorsOnHover":true,"showIndicators":false,"indicatorsPosition":"bottom","showThumbnails":true,"numVisible":10,"numVisible1536":8,"numVisible1280":6,"numVisible1024":4,"numVisible768":3,"numVisible640":2,"changeItemOnIndicatorHover":false,"images":[{"id":1701,"url":"http://localhost:10019/wp-content/uploads/2022/12/horse.jpeg","alt":"horse alt","caption":"Name some name"},{"id":1699,"url":"http://localhost:10019/wp-content/uploads/2022/12/GPJNews_Mongolia_KK_RidingChild_076_web-920x613-1.jpeg","alt":"","caption":"Name GP"},{"id":1238,"url":"http://localhost:10019/wp-content/uploads/2022/08/test-scaled.jpeg","alt":"","caption":""},{"id":458,"url":"http://localhost:10019/wp-content/uploads/2022/09/news-scaled-1.jpeg","alt":"","caption":"Paswan a mother who..."}]}';
let idx = str.indexOf('{');
console.log(str.slice(str.indexOf('/') + 1, idx));
console.log(JSON.parse(str.slice(idx)));
This example uses replace(), sub-expressions (sub-expression) and back-references $number:
let str = 'namespace/Slider {"showCaptions":true,"circular":false,"autoPlay":true,"showItemNavigators":true,"showItemNavigatorsOnHover":true,"showIndicators":false,"indicatorsPosition":"bottom","showThumbnails":true,"numVisible":10,"numVisible1536":8,"numVisible1280":6,"numVisible1024":4,"numVisible768":3,"numVisible640":2,"changeItemOnIndicatorHover":false,"images":[{"id":1701,"url":"http://localhost:10019/wp-content/uploads/2022/12/horse.jpeg","alt":"horse alt","caption":"Name some name"},{"id":1699,"url":"http://localhost:10019/wp-content/uploads/2022/12/GPJNews_Mongolia_KK_RidingChild_076_web-920x613-1.jpeg","alt":"","caption":"Name GP"},{"id":1238,"url":"http://localhost:10019/wp-content/uploads/2022/08/test-scaled.jpeg","alt":"","caption":""},{"id":458,"url":"http://localhost:10019/wp-content/uploads/2022/09/news-scaled-1.jpeg","alt":"","caption":"Paswan a mother who..."}]}';
let name = str.replace(/(namespace)\/(\w+)\s+(\{.+\})/, "$2") // Slider
let json = str.replace(/(namespace)\/(\w+)\s+(\{.+\})/, "$3") // {...}
The same example example uses match() and sub-expressions (sub-expression):
let str = 'namespace/Slider {"showCaptions":true,"circular":false,"autoPlay":true,"showItemNavigators":true,"showItemNavigatorsOnHover":true,"showIndicators":false,"indicatorsPosition":"bottom","showThumbnails":true,"numVisible":10,"numVisible1536":8,"numVisible1280":6,"numVisible1024":4,"numVisible768":3,"numVisible640":2,"changeItemOnIndicatorHover":false,"images":[{"id":1701,"url":"http://localhost:10019/wp-content/uploads/2022/12/horse.jpeg","alt":"horse alt","caption":"Name some name"},{"id":1699,"url":"http://localhost:10019/wp-content/uploads/2022/12/GPJNews_Mongolia_KK_RidingChild_076_web-920x613-1.jpeg","alt":"","caption":"Name GP"},{"id":1238,"url":"http://localhost:10019/wp-content/uploads/2022/08/test-scaled.jpeg","alt":"","caption":""},{"id":458,"url":"http://localhost:10019/wp-content/uploads/2022/09/news-scaled-1.jpeg","alt":"","caption":"Paswan a mother who..."}]}';
let matches = str.match(/(namespace)\/(\w+)\s+(\{.+\})/)
let name = matches[2] // Slider
let json = matches[3] // {...}
Using regex match and destructuring to get the relevant parts
const str = `namespace/Slider {"showCaptions":true,"circular":false,"autoPlay":true,"showItemNavigators":true,"showItemNavigatorsOnHover":true,"showIndicators":false,"indicatorsPosition":"bottom","showThumbnails":true,"numVisible":10,"numVisible1536":8,"numVisible1280":6,"numVisible1024":4,"numVisible768":3,"numVisible640":2,"changeItemOnIndicatorHover":false,"images":[{"id":1701,"url":"http://localhost:10019/wp-content/uploads/2022/12/horse.jpeg","alt":"horse alt","caption":"Name some name"},{"id":1699,"url":"http://localhost:10019/wp-content/uploads/2022/12/GPJNews_Mongolia_KK_RidingChild_076_web-920x613-1.jpeg","alt":"","caption":"Name GP"},{"id":1238,"url":"http://localhost:10019/wp-content/uploads/2022/08/test-scaled.jpeg","alt":"","caption":""},{"id":458,"url":"http://localhost:10019/wp-content/uploads/2022/09/news-scaled-1.jpeg","alt":"","caption":"Paswan a mother who..."}]}`
const [_,namespace,jsonString] = str.match(/^\w+\/(.*?) (.*)/);
console.log(namespace,JSON.parse(jsonString));
Explanation
^\w+ // any alpha string from start
\/ // forward slash
(^.*?) // group from slash to whatever comes next in this case the space
// space
(.*) // group from after space to end

Implement search feature using Regex

I have implemented the search feature using JavaScript and Regex. Firstly, I converted the input string into tokens then searched for it in the target array.
This is the sample code.
const tokens = inputString
.toLowerCase()
.split(' ')
.filter(function (token) {
return token.trim() !== ''
})
const searchTermRegex = new RegExp(tokens.join(' '), 'gim')
const filteredList = targetArray.filter(function (item) {
return item.match(searchTermRegex)
})
This code is running fine, only problem is it does not search if the words are present in random order.
For example, if target string is "scrape the data from pages", and I search for "data scrape" then it is not able to detect it.
What's the better solution for it?
Expected Output: If at least a single word from the input is present in the target string, it should show that string in the final output.
Since it's not clear whether your need both the words in your targeted result or either of them, there is an answer for either case therefore I'm adding solution if both words are need for which you'll need positive lookaheads, and it seems like your requirement is that you need to have both word complete in your inputString, that's why I've added word boundaries in the regex using \b, if that's not needed you can update the token mapper with this:
(?=.*${token})
Also I've refactored your code a little bit, hope that helps
const tokens = inputString
.split(' ')
.filter(Boolean)
.map(token => `(?=.*\\b${token}\\b)`);
const searchTermRegex = new RegExp(tokens.join(''), 'gim');
const filteredList = targetArray.filter(item => item.match(searchTermRegex));
You could do like this. I think split not necessary
const inputString = "scrape the data from pages"
const targetArray = ["data", "scrape"]
const filteredList = targetArray.every(function(item) {
return inputString.indexOf(item) > -1
})
console.log("matchStatus", filteredList)
OR Regex
const inputString = "scrape the data from pages"
const targetArray = ["data", "scrape"]
const filteredList = new RegExp(targetArray.join('|'),'gim').test(inputString)
console.log("matchStatus", filteredList)

generate two variables while using split

I have a string like this
test/something/else
I would like to generate two variables
first = test
second = something/else
I tried with
const [first, ...second] = "test/something/else".split("/");
and it gives me the right value for first but for second it's an array. So I have to join the array to get the value I need?
Use a regular expression to match a (single) / followed by anything, so that the result is the 2 strings you want:
const str = 'test/something/else';
const [, first, second] = str.match(/([^/]+)\/(.*)/);
console.log(first);
console.log(second);
If you had to use split, and you don't want the extra array, you can do something similar by putting the second part into a capture group:
const str = 'test/something/else';
const [first, second] = str.split(/\/(.*)/);
console.log(first);
console.log(second);
Correct, the idiomatic built-in command to do this is to .split() and then .join(‘’) the tail elements.
It may be (very slightly) faster to check for the index and slice the string with that, something like
function splitAt(str, delimiter) {
const idx = str.indexOf(delimiter);
const head = str.slice(0, idx);
const tail = str.slice(idx);
return [head, tail];
}
Solution is simple, we should take 2 variables, in one variable assign the string which includes '/' then in another variable assign split method split(//(.*)/) with expresion and console log it
var str = "how r u?/kkk/jj";
const [first, second] = str.split(/\/(.*)/);
console.log(first);
console.log(second);
split method break the string and assign em to arrays. The string will be break after '/' and whenever console log the item, the broken string will be displayed.

Using Regex to define variables with Discord.js?

I was advised to use regex with this discord.js project. It saves two mentions from a message into two variables in the order the two mentions are typed. Discord.js reads mentions in the numeric order of the actual IDs, not the actual typed order, so we have to use regex instead. The command string is: f$command #user1 #user2
So, here's my code:
else if (command === 'command'){
const regex = /<#!?(\d+)>/;
let match = regex.exec(message);
while (match){
const User1 = match[1].id;
const User2 = match[2].id;
}
Is this correct, and how do I make it require 2 regex matches?
else if (command === 'command') {
const regex = /<#!?(\d+)>/;
let match = regex.exec(message);
const result = [];
while (match){
result.push(match[1]);
match = regex.exec(message);
}
if (result.length !== 2) {
console.error('not 2 matches');
}
const User1 = result[0];
const User2 = result[1];
}

Overlapping named capturing groups

I'm using named capturing groups to validate and extract data out of a product number. The format of the product number looks like this:
1102961D048.075
Chars 1-2 gender_code 11
Chars 1-6 style 110296
Chars 7-8 width_code 1D
Chars 9-11 color_code 048
Char 12 delimiter ignored
Chars 13-15 size_code 075
My current code looks like this:
const validateMpn = (mpn) => {
const regex = /(?<style>\d{6})(?<width>\d{1}[ABDE])(?<color_code>\d{3})\.(?<size_code>\d{3})/gi
const match = regex.exec(mpn)
if (!match) {
return null
}
return match.groups
}
const str1 = '1102961D048.075'
const str2 = '1200322A001.085'
const match1 = validateMpn(str1)
const match2 = validateMpn(str2)
console.log(match1)
console.log(match2)
As gender_code and style overlap I'm not sure how to get them both. Therefore I have the following questions:
Is it possible to this with only one regular expression?
If yes, how could I accomplish this?
Sure, just place gender inside the style group:
const validateMpn = (mpn) => {
const regex = /(?<style>(?<gender>\d{2})\d{4})(?<width>\d{1}[ABDE])(?<color_code>\d{3})\.(?<size_code>\d{3})/gi
const match = regex.exec(mpn)
if (!match) {
return null
}
return match.groups
}
const str1 = '1102961D048.075'
const str2 = '1200322A001.085'
const match1 = validateMpn(str1)
const match2 = validateMpn(str2)
console.log(match1)
console.log(match2)
I suggest just having separate capture groups for the first two and four following characters. Then, form the style by just concatenating together the first two capture groups:
var input = "1102961D048.075";
var regex = /(.{2})(.{4})(.{2})(.{3}).(.{3})/g;
var match = regex.exec(input);
console.log("gender_code: " + match[1]);
console.log("style: " + match[1] + match[2]);
As a style note, I prefer not using named capture groups, because they tend to result in a bloated regex which is hard to read.
Yes you can capture gender_code using positive look ahead using this regex,
(?=(..))(\d{6})(\d{1}[ABDE])(\d{3})\.(\d{3})
Regex Demo
This is named groups regex but will only work in Chrome browser
and named capture grouping will be available in ECMAScript 2018 and is only supported in Chrome as of now.
This JS demo will work in Chrome as that is the only one as of now supporting EcmaScript2018,
const validateMpn = (mpn) => {
const regex = /(?=(?<gender_code>\d\d))(?<style>\d{6})(?<width>\d{1}[ABDE])(?<color_code>\d{3})\.(?<size_code>\d{3})/gi
const match = regex.exec(mpn)
if (!match) {
return null
}
return match.groups
}
const str1 = '1102961D048.075'
const str2 = '1200322A001.085'
const match1 = validateMpn(str1)
const match2 = validateMpn(str2)
console.log(match1)
console.log(match2)

Categories