Need to count the occurences of string in an array
userList=["abc#gmail.com","bca#gmail.com","abc#gmail.com"]
Need to get the count of each strings
let userList=["abc#gmail.com","bca#gmail.com","abc#gmail.com"]
Expected : [{"abc#gmail.com":2},{"bca#gmail.com":1}]
var userList=["abc#gmail.com","bca#gmail.com","abc#gmail.com"];
var result = Object.values(userList.reduce((acc, c)=>{
if(!acc.hasOwnProperty(c)) { acc[c] = {[c]:0};}
acc[c][c] += 1;
return acc;
}, {}));
console.log(result);
Hope this helps you !
You can use Array#reduce method with a reference object which keeps the index of the element.
let userList = ["abc#gmail.com", "bca#gmail.com", "abc#gmail.com"];
let ref = {};
let res = userList.reduce((arr, s) => (s in ref ? arr[ref[s]][s]++ : arr[ref[s] = arr.length] = { [s]: 1 }, arr), [])
console.log(res)
// or the same with if-else
// object for index referencing
let ref1 = {};
// iterate over the array
let res1 = userList.reduce((arr, s) => {
// check if index already defined, then increment the value
if (s in ref1)
arr[ref1[s]][s]++;
// else create new element and add index in reference array
else
arr[ref1[s] = arr.length] = { [s]: 1 };
// return array reference
return arr;
// set initial value as empty array for result
}, []);
console.log(res1)
Related
I have a array of string.
let arr=["robin","rohit","roy"];
Need to find all the common character present in all the strings in array.
Output Eg: r,o
I have tried to create a function for above case with multiple loops but i want to know what should be the efficient way to achive it.
Here's a functional solution which will work with an array of any iterable value (not just strings), and uses object identity comparison for value equality:
function findCommon (iterA, iterB) {
const common = new Set();
const uniqueB = new Set(iterB);
for (const value of iterA) if (uniqueB.has(value)) common.add(value);
return common;
}
function findAllCommon (arrayOfIter) {
if (arrayOfIter.length === 0) return [];
let common = new Set(arrayOfIter[0]);
for (let i = 1; i < arrayOfIter.length; i += 1) {
common = findCommon(common, arrayOfIter[i]);
}
return [...common];
}
const arr = ['robin', 'rohit', 'roy'];
const result = findAllCommon(arr);
console.log(result);
const arr = ["roooooobin","rohit","roy"];
const commonChars = (arr) => {
const charsCount = arr.reduce((sum, word) => {
const wordChars = word.split('').reduce((ws, c) => {
ws[c] = 1;
return ws;
}, {});
Object.keys(wordChars).forEach((c) => {
sum[c] = (sum[c] || 0) + 1;
});
return sum;
}, {});
return Object.keys(charsCount).filter(key => charsCount[key] === arr.length);
}
console.log(commonChars(arr));
Okay, the idea is to count the amount of times each letter occurs but only counting 1 letter per string
let arr=["robin","rohit","roy"];
function commonLetter(array){
var count={} //object used for counting letters total
for(let i=0;i<array.length;i++){
//looping through the array
const cache={} //same letters only counted once here
for(let j=0;j<array[i].length;j++){
//looping through the string
let letter=array[i][j]
if(cache[letter]!==true){
//if letter not yet counted in this string
cache[letter]=true //well now it is counted in this string
count[letter]=(count[letter]||0)+1
//I don't say count[letter]++ because count[letter] may not be defined yet, hence (count[letter]||0)
}
}
}
return Object.keys(count)
.filter(letter=>count[letter]===array.length)
.join(',')
}
//usage
console.log(commonLetter(arr))
No matter which way you choose, you will still need to count all characters, you cannot get around O(n*2) as far as I know.
arr=["robin","rohit","roy"];
let commonChars = sumCommonCharacters(arr);
function sumCommonCharacters(arr) {
data = {};
for(let i = 0; i < arr.length; i++) {
for(let char in arr[i]) {
let key = arr[i][char];
data[key] = (data[key] != null) ? data[key]+1 : 1;
}
}
return data;
}
console.log(commonChars);
Here is a 1 liner if anyone interested
new Set(arr.map(d => [...d]).flat(Infinity).reduce((ac,d) => {(new RegExp(`(?:.*${d}.*){${arr.length}}`)).test(arr) && ac.push(d); return ac},[])) //{r,o}
You can use an object to check for the occurrences of each character. loop on the words in the array, then loop on the chars of each word.
let arr = ["robin","rohit","roy"];
const restWords = arr.slice(1);
const result = arr[0].split('').filter(char =>
restWords.every(word => word.includes(char)))
const uniqueChars = Array.from(new Set(result));
console.log(uniqueChars);
I have a string in the form
Key=asdf, num=90, Key=ert, num=20, Key=yged, num=20, Key=kned, num=35
I have to filter only Key num pairs which has value 20 and store them into a Key Value pair such that Key=ert, num=20 will be first record and Key=yged, num=20 will be second record so on. How can I use Map in JavaScript so that always first value will go as key and second will go as value and form pairs in this case. I have used the following :
var dataString = JSON.parse(data).data;
var arrayVal = new Array();
arrayVal = dataString.split(', ');
for(a in arrayVal){
console.log(arrayVal[a]);
}
Array.map probably isn't the best tool for the job here. Array.reduce would be a better approach. Since you know what your delimiters are (namespaces and equal signs), you can logically split things up so that you know that every other iteration will give you a key/value. You can then create a mechanism to track what the last key is so you can map the value to it.
const str = 'Key=asdf, num=90, Key=ert, num=20, Key=yged, num=20, Key=kned, num=35';
const arr = str.split(', ').reduce( (acc, curr) => {
const entry = curr.split('=');
const key = entry[0];
const val = entry[1];
if (key === 'Key') {
acc['last_key'] = val
acc[val] = null;
} else if (key === 'num') {
acc[acc['last_key']] = val;
}
return acc;
}, {});
delete arr.last_key;
console.log(arr);
Here you go. It's kinda ugly.
let result = dataString.split(', ')
.map((value, index, array) =>
value === 'num=20' && array[index - 1])
.filter(x => x);
console.log(result);
Here's my say
const dataString = JSON.parse(data).data;
const arrayVal = dataString.split(', ');
const obj = {}; // initialize the object
for (let i = 0; i < arrayVal.length; i += 2) { // Iterating over two elements for the key and value
const key = arrayVal[i].split('=')[1];
const value = arrayVal[i + 1].split('=')[1];
obj[key] = value;
}
console.log(obj);
What I have:
var test ='1=Car&2=Bike&10=rabbit&10=dog&10=horse&11=ferrari&11=mercedes';
is a string, which I split and convert to array. I want that for every value that contains the same starting number, they get merged into the same value.
Example, the string above becomes tha array I don't want:
[ "1=Car", "2=Bike", "10=rabbit", "10=dog", "10=horse", "11=ferrari", "11=mercedes" ]
What I want, instead:
[ "1=Car", "2=Bike", "10=rabbit,dog,horse", "11=ferrari,mercedes" ]
My actual code:
var test ='1=Car&2=Bike&10=rabbit&10=dog&10=horse&11=ferrari&11=mercedes';
var array = test.split('&');
console.log(array);
var check_multiselect = null;
var current_multiselect = null;
for (const [key, value] of Object.entries(array)) {
var obj = value.split('=');
if (obj[0] == check_multiselect) {
console.log(current_multiselect);
current_multiselect = key - 1;
array[current_multiselect] = array[current_multiselect] +', '+obj[1];
}
check_multiselect = obj[0];
};
console.log(array);
Which does not work as expected. What's wrong in there?
You could find same starting number and update the value.
var test ='1=Car&2=Bike&10=rabbit&10=dog&10=horse&11=ferrari&11=mercedes',
result = test
.split('&')
.reduce((r, string) => {
let [key, value] = string.split('='),
index = r.findIndex(q => q.split('=')[0] === key);
if (index === -1) r.push(string);
else r[index] += ',' + value;
return r;
}, []);
console.log(result);
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 have a database in Firebase, which I then convert to an array, this is my code:
let timeRef = firebase.database().ref('root/grupo0/user0/0');
function snapshotToArray(snapshot) {
let returnArr = [];
snapshot.forEach(function(childSnapshot) {
let item = childSnapshot.val();
item.key = childSnapshot.key;
returnArr.push(item);
});
return returnArr;
};
const timeRefArray = timeRef.on('value', function(snapshot) {
console.log(snapshotToArray(snapshot));
});
Each element is like this: ^MED~#1550648873
How can I return each element only with numbers?
I think you want just only the number included in the item string. Then, you need a regex to get the number. In your code, replace the line returnArr.push(item); with:
var m = /\d+/.exec(item);
if (m) {
returnArr.push(m[0] * 1);
}
The *1 is to cast the number to integer.
You can use string.match() with a regex to extract the digit, then convert the result to a number with parseInt. You can then conditionaly push the item to the array if it is not NaN:
const items = ['^MED~#1550648873', '^MED~#'];
const returnArr = [];
items.forEach(item => {
const value = parseInt((item.match(/\d+/) || [''])[0]);
!isNaN(value) && returnArr.push(value);
});
console.log(returnArr);
Try This:
var arr = [ '^MED~#1550648873','Am2mm55','^MED' ] ;
var patt = new RegExp('\\d+','g') ;
var result = arr.reduce( (acc, ele) => {
if ( isTrue = ele.match(patt) ) { acc.push( isTrue.join('') ) ; }
return acc ;
}, []) ;
console.log( result ) ;
when returning each element to array you can use replace method:
str = item.replace(/\D/g,'');
returnArr.push(str);
then you can cut the non numeric part, before push it to your array.