Supposed I have a string of
let check = 'test_name=sdf&test_name=dfgdfg&test_last_name=dfg';
Is there a way in js where i can merge the duplicates and just append the value of it with comma
the output should be
test_name=sdf,dfgdfg&test_last_name=dfg;
any idea how can i do it
this is what i have tried so far
this is the simplfied version
test2: function() {
let test2 = ['val1','val2','val3'];
let test3 = ['opt1','opt1','opt3'];
let filter = '';
for (let i = 0; i < test2.length; i++) {
let text = test2[i]; // input value
let val =test3[i]; // option value
filter += val + '=' + text;
if (filter.includes(val) === true) {
filter += ',' + text;
}
i !== test2.length-1 ? filter += '&' : '';
}
console.log(filter);
},
the output is opt1=val1,val1&opt2=val2,val2&opt3=val3,val3
You can split the string first by & and then map through values and split them again using =, now using reduce and Map we club the values with same key name, and in the end join them to get the same structure as original string
let check = 'test_name=sdf&test_name=dfgdfg&test_last_name=dfg';
let final = check.split('&').map(v=>v.split('=')).reduce((r,[k,v])=>{
r.set(k, (r.get(k)||[]).concat(v))
return r
},new Map())
let output = [...final].map(v=>`${v[0]}=${v[1].join(',')}`).join('&')
console.log(output)
Related
I have two arrays containing some parameter values. All elements in the arrays are strings like the following:
x = [ "vorzugsreihe=J", "nennleistung=94,1127", "nenndrehzahl=31,9400"]
y = ["nenndrehzahl=500,3000"]
Expected Output would be:
x = [ "vorzugsreihe=J", "nennleistung=94,1127", "nenndrehzahl=500,3000"]
I have tried using Array.Filter but can't seem to be able to filter only partially (like starting with the string instead of the whole string since that won't match as the values are different).
What I'd like is to be able to go through each element from array Y, and search if the element(string before "=") exists in array X and replace the value(s) of that element in array X.
for(var i=0;i<x.length;i++){
var currentStr = x[i];
var currentInterestedPart = /(.+)=(.+)/.exec(currentStr)[1];
var replacePart = /(.+)=(.+)/.exec(currentStr)[2];
for(var j=0;j<y.length;j++){
if(!y[j].startsWith(currentInterestedPart)) {continue;}
var innerReplacePart = /(.+)=(.+)/.exec(y[j])[2];
x[i] = currentStr.replace(replacePart,innerReplacePart);break;
}
}
Try this. This makes use of RegEx and it is less error prone.
You can use Map and map
First create a Map from array y, split each element by = use first part as key and second part as value
Loop over x array, split each element by = and use first part as key to search in Map if it's present use value from Map else return without any change
let x = ["vorzugsreihe=J", "nennleistung=94,1127", "nenndrehzahl=31,9400"]
let y = ["nenndrehzahl=500,3000"]
let maper = new Map(y.map(v => {
let [key, value] = v.split('=', 2)
return [key, value]
}))
let final = x.map(v => {
let [key, value] = v.split('=', 2)
if (maper.has(key)) {
return key + '=' + maper.get(key)
}
return v
})
console.log(final)
For each value in the y array, iterate and check if the word exist in the x array. Once you find a match just update the value. (The below solution mutates the original array)
const x = [ "vorzugsreihe=J", "nennleistung=94,1127", "nenndrehzahl=31,9400"],
y = ["nenndrehzahl=500,3000"],
result = y.forEach(word => {
let [str, number] = word.split('=');
x.forEach((wrd,i) => {
if(wrd.split('=')[0].includes(str)) {
x[i] = word;
}
});
});
console.log(x);
I'd suggest using combination of reduce + find - this would accumulate and give you the results you're expecting.
var x = [ "vorzugsreihe=J", "nennleistung=94,1127", "nenndrehzahl=31,9400"]
var y = ["nenndrehzahl=500,3000"]
var combinedArr = x.reduce((acc, elem, index) => {
const elemFoundInY = y.find((yElem) => yElem.split("=")[0] === elem.split("=")[0]);
if (elemFoundInY) {
acc = [...acc, ...[elemFoundInY]]
} else {
acc = [...acc, ...[elem]];
}
return acc;
}, [])
console.log(combinedArr);
You can use .startsWith() to check if element start with key= and then replace its value:
let x = [ "vorzugsreihe=J", "nennleistung=94,1127", "nenndrehzahl=31,9400"];
let y = ["nenndrehzahl=500,3000"];
y.forEach(val => {
let [key, value] = val.split("=");
for (let i = 0; i < x.length; i++) {
if (x[i].startsWith(`${key}=`)) x[i] = `${x[i].split("=")[0]}=${value}`;
}
})
console.log(x)
Try this:
y.forEach(item => {
const str = item.split("=")[0];
const index = x.findIndex(el => el.startsWith(str));
if (index) {
const split = x[index].split('=');
x[index] = `${split[0]}=${split[1]}`;
}
})
I am using only Javascript.
I have the following string :
?pn1=age&pn2=name&pv1=12&pv2=alice
What I need to do, is have the following outcome :
age:12|name:alice
I thought of a way to do this, it is the following :
var str = "?pn1=age&pn2=name&pv1=12&pv2=alice";
var strSplit = str.split("&");
for (var i = 0; i < strSplit.length; i++) {
console.log(strSplit[i]);
}
This returns the following result :
?pn1=age
pn2=name
pv1=12
pv2=alice
Since I want to join together pn1 and pv1 and pn2 and pv2, the number present in the end of the string is important.
?pn1=age
pn2=name
pv1=12
pv2=alice
So I thought a way to do this is to sort the array by this number. and then joining every 2 values together after sorting.
I tried the following code :
strSplit.sort(function() {
var pref = strSplit[i].split('=')[0];
return pref.charAt(pref.length-1);
});
It does not seem to work
Any help would be appreciated
You could split the parts, collect all items and return a joined string.
var string = '?pn1=age&pn2=name&pv1=12&pv2=alice',
result = string
.slice(1)
.split('&')
.reduce((r, p) => {
var [k, value] = p.split('='),
[key, index] = k.split(/(\d+)/);
index--;
r[index] = r[index] || {};
r[index][key] = value;
return r;
}, [])
.map(({ pn, pv }) => [pn, pv].join(':'))
.join('|');
console.log(result);
You can do that in following steps.
You can loop through half of the array and add corresponding keys and values to an array.
Consider i is the current index when we loop through half array.
The element at position i will be key.
Add the half of the length and add it to i to get corresponding value.
split() both key and value by = and get the second element.
var str = "?pn1=age&pn2=name&pv1=12&pv2=alice";
var arr = str.split("&");
let half = arr.length/2
let res = [];
for (var i = 0; i < half; i++) {
res.push(`${arr[i].split('=')[1]}:${arr[i + half].split('=')[1]}`);
}
console.log(res.join('|'))
You could use URLSearchParams to convert the query string to a collection of key-value pair.
Then loop through them to group the the pv and pn values based on the number.
Separate the string and and number values using the regex: (\D+)(\d+)
Loop through the obj.pn and get the corresponding pv value for the same number
Join the resulting array with |
This works with pn and pv values in any random order
const searchParams = new URLSearchParams("?pn1=age&pn2=name&pv1=12&pv2=alice")
const obj = { pn: {}, pv: {} }
for (let [key, value] of searchParams) {
const [, k, number] = key.match(/(\D+)(\d+)/)
obj[k][number] = value
}
const output = Object.entries(obj.pn)
.map(([n, key]) => `${key}:${obj.pv[n]}`)
.join("|")
console.log(output)
One idea is to first split values on & and add it to take digit as key and place on object and then later place the respective values in desired format
var str = "?pn1=age&pn2=name&pv1=12&pv2=alice".replace(/^\?/,'')
var strSplit = str.split("&");
let op = strSplit.reduce((op,inp) => {
let [key,value] = inp.split('=')
let digit = key.match(/\d+/)[0]
op[digit] = op[digit] || []
op[digit].push(value)
return op
},{})
let final = Object.values(op).reduce((op,inp) => {
let [key,value] = inp
op.push(`${key}:${value}`)
return op
} ,[]).join(' | ')
console.log(final)
You could convert that & split to a string and remove the ?xxx= then split it again by , to finally have an array with the stuff you're looking at.
var str = "?pn1=age&pn2=name&pv1=12&pv2=alice";
var split = str.split('&').toString().replace(/([?]?[pnv0-9]+[=])/g,'').split(',');
console.log(split[0] + ':' + split[2] + '|' + split[1] + ':' + split[3]);
EDIT : worth mentioning for those who are looking to the best performing solution, I tested all those provided here, click here for more infos.
The solution's list from the fastest to the slowest :
Maheer Ali (113,610 ops/s ±1.48% fastest)
tcj (112,324 ops/s ±1.01% 1.13% slower)
Nina Scholz (81,067 ops/s ±1.81% 28.64% slower)
Code Maniac (80,074 ops/s ±0.99% 29.52% slower)
adiga (33,065 ops/s ±0.92% 70.9% slower)
I'm a beginner in learning javascript, need to retrieve a specific part of value from the string.
below is the format of string provided by my teammates, they are a set of parameter and its value separated by a colon.
how can I retrieve the value, once input the parameter name, then return the value just before the next colon?
string = "productCat:Wine:country:Australia:year:2000:type:white wine:"
example:
if input 'productCat', then return 'Wine'
if input 'country', then return 'Australia'
if input 'year', then return '2000'
if input 'type', then return 'white wine'
thanks!
Here's an example that will be compatible with older browsers.
var string = "productCat:Wine:country:Australia:year:2000:type:white wine:"
function getPart(string, input) {
var parts = string.split(":");
for (var i = 0; i < parts.length; i = i + 2) {
if (parts[i] == input) {
return parts[i+1];
}
}
}
console.log(getPart(string, "productCat"));
First split your string into array of strings using split() function
string="productCat:Wine:country:Australia:year:2000:type:white wine:"
var array=string.split(":");
Second according to input return the value which is index+
return var x=array[array.indexOf(input)+1];
Here is a small example. Just split the string, then look for the next index if something is found.
But this is not very smart.
const string = 'productCat:Wine:country:Australia:year:2000:type:white wine';
const findNext = (data, str) => {
const array = data.split(':');
const i = array.indexOf(str);
if(i >= 0) return array[i+1];
}
console.log(findNext(string, 'productCat'));
console.log(findNext(string, 'country'));
Here is what I would do if I were you:
const string = 'productCat:Wine:country:Australia:year:2000:type:white wine';
const parseString = str => {
const array = str.split(':');
const result = {};
for(let i = 0; i<array.length; i=i+2) {
result[array[i]] = array[i+1];
}
return result;
}
const result = parseString(string);
console.log(result);
console.log(result.country);
console.log(result.year);
Just parse the string and build an object you'll use easily later ;)
I have to arrays which are related.
shortArray = ["ID-111", "ID-222"]
longArray = ["ID-111 bis", "ID-222 bis"]
I created them like that because I needed unique IDs in previous steps and now I must use the same color for each pair in the chart I'm drawing them.
My aim is to generate a string with this form:
{
"ID-111 bis" : chart.color("ID-111"),
"ID-222 bis" : chart.color("ID-222"),
...
}
I tried to do it like this:
const result = {}
for(const item of longArray) {
result[item]=[];
result[item].push({item : "chart.color(" + shortArray+ ")"});
}
Which gives me this wrong output:
{
"ID-111 bis" :[{item: "chart.color(ID-111,ID-222)"}],
"ID-222 bis" :[{item: "chart.color(ID-111,ID-222)"}]
}
Any ideas what should I change?
LATER EDIT:
I saw many answers which are pretty similar but there is a condition that must be respected:
The second argument should not be in quotes.
"ID-111 bis" : chart.color("ID-111") - good
"ID-111 bis" : "chart.color("ID-111")" - bad
You need to use the item's value instead of actualValue which seems to be some static value and is not dependent on item in your logic
And every array item seems to be a new array, which is not what you are looking for
result[item] = {item : "chart.color(" + item.split(" ")[0] + ")"};
Even more precisely
var finalValue = {};
shortArray.forEach( function(s){
finalValue[s+" bis"] = chart.color(s); //assuming that chart.color is the function you want to invoke
})
Why are you making an array and pushing an element inside ? If you want to get layout like:
{
"ID-111 bis" : chart.color("ID-111"),
"ID-222 bis" : chart.color("ID-222"),
...
}
simply remove the [] part.
const result = {}
for(const item of longArray) {
result[item] = { "item" : "chart.color(" + shortArray+ ")"});
}
If both arrays have the same length:
shortArray = ["ID-111", "ID-222"]
longArray = ["ID-111 bis", "ID-222 bis"]
result = {}
for (var i = 0; i < longArray.length; i++) {
result[ longArray[i] ] = "chart.color(" + shortArray[i] + ")";
}
https://jsfiddle.net/47qcrvqh/
You can use .reduce function of array
var shortArray = ["ID-111", "ID-222"]
var longArray = ["ID-111 bis", "ID-222 bis"]
var result = longArray.reduce((res,key,index)=>{
// Can call chart.color without quotes if that's requirement
res[key] = 'chart.color("'+shortArray[index]+'")';
return res;
},{})
console.log(result)
You should execute the chart.color(actualTitle) so it will return a value, Try :
const result = {}
for (var i = 0; i < longArray.length; i++)
{
result[longArray[i]] = 'chart.color("' + shortArray[i] + '")';
// result[longArray[i]] = chart.color(shortArray[i]);
}
Hope this helps.
shortArray = ["ID-111", "ID-222"]
longArray = ["ID-111 bis", "ID-222 bis"]
const result = {}
for (var i = 0; i < longArray.length; i++) {
result[longArray[i]] = 'chart.color("' + shortArray[i] + '")';
// result[longArray[i]] = chart.color(shortArray[i]);
}
console.log(result);
I have an array which looks like
var arr = ["a|c", "a|e", "x|z"];
for(var x in arr){
var appsplit = x.split("|");
}
If the first value(ex: a) in the elements matches then it should combine the values
Ex: output
ace
xz
Please advice how this approach can be done.
You are testing everyone's reading comprehension with that riddle.
var pairs = {};
var arr = ["a|c", "a|e", "x|z"];
for(var x in arr)
{
var appsplit = arr[x].split("|");
if(pairs[appsplit[0]] !== "undefined")
{
pairs[appsplit[0]] = pairs[appsplit[0]] + appsplit[1];
}
else
{
pairs[appsplit[0]] = appsplit[1];
}
}
var matches = [];
for(var x in pairs)
{
matches.push(x + pairs[x]);
}
console.log(matches);
We need to map out the arr elements in this object called pairs. The first value in your split would be the key and the second value is appended (or assigned if it's the first match to the key)
You made an error of splitting x, but you are only splitting the index of the element, not the actual value of the element. arr[x] is the actual value, where x specifies the index in the array.
After we've gone through your arr, we can now merge the key with the values. Your output is contained in matches where the key in each pair is prepended to the value of the key's pair.
Some simple code that would to the trick here.
var arr = ["a|c", "a|e", "x|z", "c|b", "z|e", "c|a"];
var resultObj = {};
arr.forEach(function(element, index){
var array = element.split('|');
if(array.length!==2){
console.log("skipping, invalid input data", element);
} else {
var firstLetter = array[0];
var secondLetter = array[1];
if(resultObj[firstLetter]){
resultObj[firstLetter].push(secondLetter);
} else {
resultObj[firstLetter]=[secondLetter];
}
}
});
Object.keys(resultObj).forEach(function(key){
console.log(key + "," + resultObj[key]);
});
You can use .reduce(), Set to not accumulate duplicate values, .some() to check if previous array contains value in current array, .map(), Array.from() and .join() to convert array to string
var arr = ["a|c", "a|e", "x|z"];
var res = arr.reduce(function(a, b) {
var curr = b.split("|");
var set = new Set;
for (let prop of curr) set.add(prop);
if (!a.length) {
a.push(set)
} else {
for (prop of a) {
if (curr.some(function(el) {
return prop.has(el)
})) {
for (el of curr) {
prop.add(el)
}
} else {
for (let prop of curr) set.add(prop);
a.push(set)
}
}
}
return a
}, []).map(function(m) {
return Array.from([...m], function(el) {
return el
}).join("")
});
console.log(res);
I feel like this can be done more elegantly, but I didn't have time to streamline it. :) The below code will do what you want, though:
var aStartArray = **ARRAY_VALUE_HERE**;
var aSplitResultStrings = [];
// step through each element in the array
for (var i = 0, iSALength = aStartArray.length; i < iSALength; i++) {
// split the values for the current array element
var aSplitVal = aStartArray[i].split("|");
var bStringDoesNotExist = true;
// loop through the "result strings" array
for (var j = 0, iSRSLength = aSplitResultStrings.length; j < iSRSLength; j++) {
// if the first letter from the array element = the first letter of the current "result string" . . .
if (aSplitResultStrings[j].charAt(0) === aSplitVal[0]) {
// append the second letter of the array value to the current result string
aSplitResultStrings[j] = aSplitResultStrings[j] + aSplitVal[1];
// indicate that a match has been found and exit the "result string" loop
bStringDoesNotExist = false;
break;
}
}
// if there are no result strings that start with the first letter of the array value . . .
if (bStringDoesNotExist) {
// concatenate the two values in the current array value and add them as a new "result string"
aSplitResultStrings.push(aSplitVal[0] + aSplitVal[1]);
}
}
Using these arrays, the results are:
aStartArray = ["a|c", "a|e", "x|z"] //results in:
aSplitResultStrings = ["ace", "xz"]
aStartArray = ["a|b", "a|c", "a|d", "a|e", "x|y", "x|z"] //results in:
aSplitResultStrings = ["abcde", "xyz"]
aStartArray = ["a|b", "d|e", "d|f", "x|y", "g|h", "g|i", "m|n", "g|j", "a|c", "x|z"] //results in:
aSplitResultStrings = ["abc", "def", "xyz", "ghij", "mn"]
As I said, this could be more elegant (for example, you could probably use Map to make iterating through the "result strings" easier), but this makes the steps pretty clear and should get you going down the right path towards a final solution.