Using trim more than once in an array JS - javascript

I have a snippet of code where I am trying to parse a longer string with special characters into an array with no spaces or special characters.
input: name: this is some stuff, name2: this is more stuff
desired output: [name,this is some stuff,name2,this is more stuff]
current output: z.trim isn't a function
function parseOrder(custOrder) {
const custOrderArr = custOrder.split(',');
const trimedArr = custOrderArr.map((x) => x.trim());
const numberArr = trimedArr.map((y) => y.split(':'));
const processArr = numberArr.map((z) => z.trim());
console.log(processArr);
}
Why does trim work the first time and not the second?

You can not trim an array. But you could map the array and trim the values.
This result features Array#flatMap for preventing arrays with pairs.
function parseOrder(custOrder) {
return custOrder
.split(',')
.flatMap(y => y.split(':').map(x => x.trim()));
}
var input = 'name: this is some stuff, name2: this is more stuff ';
console.log(parseOrder(input));

Try to split by two signs, then trim your elements:
const result = str.split(/[\:,]+/).map(s => s.trim());
An example:
let str = 'test: It is me, test2: it is me 2 ';
console.log(str.split(/[\:,]+/).map(s => s.trim()));

Related

Replace certain values in a string based on a mapping - JS

I have a string with words followed by a colon. I need to replace the colon words in that string with values from an object. I was able to extract out the colon words but not sure on the best way to replace it in the string.
This is what I have:
const string = 'This is :state :buttonName by :name';
const buttonName = 'button link';
const data = {
state: 'Alabama',
name: 'Arun'
}
const res = string.match(/:[a-zA-Z]+/g).map(i => i.replace(':', ''))
console.log(res)
// This is Alabama button link by Arun
End result should be
This is Alabama button link by Arun
Please advice.
First of all, you need to move const buttonName = 'button link'; to the array.
You need to use String#replace, but also you need to capture the part of the regex after : and actually use the Group #1 value as key to get the right data value.
Besides, you need to check if the extracted key is inside the dictionary to avoid issues.
You can use
const string = 'This is :state :buttonName by :name';
const data = {
buttonName: 'button link',
state: 'Alabama',
name: 'Arun'
}
const res = string.replace(/:([a-zA-Z]+)/g, (m, i) => i in data ? data[i] : m)
console.log(res)
You can split the string and then call array map to replace words and the join to final string
const str= 'This is :state :buttonName by :name';
str.split(' ').map(a => {
if(a.startsWith(":"))
return data[a.replace(":","")];
return a;
}).join(' ');
If you've already stripped the ":" from the string you can just iterate your object keys and replace them with the respective values.
...
const res = string.match(/:[a-zA-Z]+/g).map(i => i.replace(':', ''))
for (const [key, value] of Object.entries(data)) {
res = res.replaceAll(key, value);
}
Wiktor's answer is good. But if it needs to replace the global variable as well, we can write the code as belows.
const res = string.replace(/:([a-zA-Z_]+)/g, (m, i) => data[i] ?? eval(i) ?? m);
console.log(res)
This code didn't do exception handling yet. It should be in consideration. So we can define a replacer function handling exception
const replacer = (m, i) => {
try {
return data[i] ?? eval(i);
} catch {
return m;
}
}
const res = string.replace(/:([a-zA-Z_]+)/g, replacer);

Javascript Split String in Array to Objects in Array

I have this Array ["2.900000F02A_1313_01","2.600000F02A_1315_03","2.900000F02A_1354_01"]
And I want to split it like this:
[
{"name":"F02A_1313_01", "Voltage":"2.900000"},
{"name":"F02A_1315_03", "Voltage":"2.600000"},
{"name":"F02A_1354_01", "Voltage":"2.900000"}
]
This is my Code that doesn't work:
for (var i in msg.strg) {
array.push(i.split(/[a-zA-Z].*/g));
}
Does somebody know how I can do this?
You could split with a group.
const
data = ["2.900000F02A_1313_01", "2.600000F02A_1315_03", "2.900000F02A_1354_01"],
result = data.map(string => {
const [Voltage, name] = string.split(/([a-z].*$)/i);
return { name, Voltage };
});
console.log(result);
You could also make the match a bit more specific, matching the digits for Voltage (\d+(?:\.\d+)?) in group 1 , and a case insensitive char a-z followed by word characters (F\w+) in group 2.
const arr = ["2.900000F02A_1313_01","2.600000F02A_1315_03","2.900000F02A_1354_01"];
const result = arr.map(s => {
const m = s.match(/^(\d+(?:\.\d+)?)([a-z]\w+)$/i);
return {name: m[2], Voltage: m[1]}
});
console.log(result);

Split whitespaces and search user input

I have an input field where users can search a database for a certain name. The database contains names such as "Doe, John".
If a user searches for "john" I think it's easy to implement. However, if he or she searches for "john Doe" I would like to implement the logic search for john or search for doe.
With RegEx I am completely lost. Is something like this even possible? However, with JS I would at least be able to consider this algorithm:
Split the input on a whitespace and create to arrays
Remove special characters
Filter the JSON object retrieved from the database
check, whether item includes the cleansed string-arrays
As for the JS-functions I tried something (in vain):
let search = 'John Doe' //user input
let data = ['Doe, John', 'Bean, Mister'] //data from database
let split = search.split(" ") //split the whitespace into two arrays
split = split.map(item => { return item.replace(/[^\w\s]+/gi, '')}) //remove dots, commas etc.
let result = data.filter(item => { //filter each item from the data...
split.forEach(element => {
let found = item.match(new RegExp(element, "i")) // so here I get matches, but how can I move them up the let the filter method return true?
return found.length
}).length>0
})
console.log(result)
Thanks to Taplars comment, I have used a map-method instead of a forEach:
let data = ['Doe, John', 'Bean, Mister']
let split = search.split(" ")
split = split.map(item => { return item.replace(/[^\w\s]+/gi, '')})
let result = data.filter(item => {
let filtered = split.map(element => {
let ret = item.match(new RegExp(element, "i"))
return ret
})
console.log(item,filtered) //now I have two arrays, one with something meaningful and one with [null,null]. How can I remove empty arrays?
return filtered.length>0
})
console.log(result)
Try the following:
Get the search expression and turn it into a series of regular expressions
Iterate through the data and check to see if some or all the expressions match
const data = ['Doe, John', 'Doe, Jane', 'Smith, John', 'Bean, Mister'] // data from database
function searchEvery(input) {
const wordExpressions = input.split(/[^\w]+/g)
.filter(word => word) // remove empty entries
.map(word => new RegExp(word, 'i')); // convert to regular expression
return data.filter(item => wordExpressions.every(exp => exp.test(item)));
}
function searchSome(input) {
const wordExpressions = input.split(/[^\w]+/g)
.filter(word => word) // remove empty entries
.map(word => new RegExp(word, 'i')); // convert to regular expression
return data.filter(item => wordExpressions.some(exp => exp.test(item)));
}
console.log(searchEvery('John Doe'))
console.log(searchEvery('John'))
console.log(searchEvery('Doe'))
console.log(searchSome('John Doe'))
If you want to make it non-greedy (every user word is optional)
const data = ['Doe, John', 'Bean, Mister', 'Mardoe, Ann']; // data
const search = ' joh doe '; // user input
// Remove spaces and create Piped | options
const searchPipe = search.trim().replace(/[|\s]+/g, '|');
const result = data.filter(item => new RegExp(searchPipe, 'i').test(item));
console.log(result)
To make it greedy (must contain every word)
const data = ['Doe, John', 'Bean, Mister', 'Mardoe, Ann']; // data
const search = ' joh doe '; // user input
// Remove extra spaces and create array
const searchArr = search.trim().replace(/\s+/g, ' ').split(' ');
const result = data.filter(item => searchArr.every(sa => new RegExp(sa, 'i').test(item)));
console.log(result)
Notice, if a person named "Doe, Doe" was in the list, the above would account it (since the length) for a "john doe" search, but I think it's fine.

How to turn a string onto a map?

I need to turn a string formatted like that:
string = "John:31,Miranda:28"
Onto this;
obj = { "John" => 31, "Miranda" => 28 }
I did this :
const class = new Map();
array = string.split(",");
And obviously I do not know what do with it because after the split I get something like this:
["John:31", "Miranda:28"]
And I don't know how to turn it onto an object (using the ":" as a arrow)... Maybe I don't need to use the array as an intermediary? Any thoughts? Thanks
You can use split to split by comma, and then map on the resulting strings to split again by colon, and feed the resulting array of arrays into the Map constructor.
For instance, if you want the map keyed by the names, which I suspect you do:
const string = "John:31,Miranda:28"
const map = new Map(string.split(",").map(entry => entry.split(":")));
console.log(map.get("John")); // "31" (a string)
If you want the numbers to be numbers, not strings, you'll need to convert them:
const string = "John:31,Miranda:28"
const map = new Map(string.split(",").map(entry => {
const parts = entry.split(":");
parts[1] = +parts[1];
return parts;
}));
console.log(map.get("John")); // 31 (a number)
My answer here goes into some detail on your options for converting from string to number.
If you want the map keyed by value instead (which I suspect you don't, but...), you just have to reverse the order of the inner array entries:
const string = "John:31,Miranda:28"
const map = new Map(string.split(",").map(entry => {
const [name, num] = entry.split(":");
return [num, name];
}));
console.log(map.get("31")); // John
So split on the commas, loop over it and split on the colon, and build the object.
var myString = "John:31,Miranda:28"
var myObj = myString.split(',').reduce(function (obj, part) {
var pieces = part.split(':')
obj[pieces[0]] = pieces[1]
return obj
}, {})
You could try something like this:
const data = "John:31,Miranda:28"
const splitData = data.split(',')
const result = splitData.reduce((newObject, item) => {
const [name, age] = item.split(':')
return {
...newObject,
[name]: parseInt(age)
}
}, {})
console.log(result)
I'll just add this here:
Basically, split string by the comma, then the colon.
Combine result into a map
const test = "John:31,Miranda:28";
console.log(test);
const obj = test.split(/,/).map(item => item.split(/:/));
console.log(obj);
const _map = new Map(obj);
console.log(_map);
console.log(_map.get("John"))

Camelcase string to normal string

How to change NoOfSAP => No Of SAP? I have trying the replace method but it says undefined.
function unCamlelCase(result) {
return result.key.replace(/([^A-Z]*)([A-Z]*)([A-Z])([^A-Z]*)/g, '$1 $2 $3$4')
.replace(/ +/g, ' ');
};
How can I change the result key values camel case to normal string?
if (exactMatch) {
const { ...response } = json[0];
const result = Object.keys(response).reduce((acc, key) => {let newKey = key.charAt(0).toUpperCase() + key.slice(1);
return acc;
}, {});
You could use the following expression with a few helper methods to clean up the output:
"NoOfSAP".split(/([A-Z][a-z]+)/).filter(Boolean).join(' ');
This will match all upper case letters followed by one or more lower-case letters and split each chunk into an array. .filter(Boolean) is then used to remove any empty strings in the array and .join is then used to add spaces between the strings in the array.
See example below:
const getWords = wrd =>
wrd.split(/([A-Z][a-z]+)/).filter(Boolean).join(' ');
console.log(getWords("NoOfSAP")); // No Of SAP
console.log(getWords("ThisIsAWord")); // This Is A Word (notice how it will split individual letters such as A)
console.log(getWords("IAmAHuman")); // I Am A Human
console.log(getWords("JSIsGreat")); // JS Is Great (notice how it understands JS and Is are two seperate words and doesn't give JSI s Great)
As per your question about changing the keys in your object to the "uncamelcased" keys you can use .map with Object.keys to generate your result:
const getWords = wrd =>
wrd.split(/([A-Z][a-z]+)/).filter(Boolean).join(' ');
const obj = {
"NoOfSAP": 1,
"NoOfBUN": 2,
"NoOfBRE": 3,
"NoOfPEA": 4
}
const result = Object.keys(obj).map(getWords);
console.log(result);
You can go that way:
const camelToWords = (camelCaseWord) => camelCaseWord
.replace(/([A-Z]+)/g, " $1")
.replace(/([A-Z][a-z])/g, "$1");
There is also possibility to use existing libraries like lodash:
const _ = require('lodash');
console.log(_.startCase('abcDef'));
// result: Abc Def

Categories