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);
For example i am having an array of data as below
var arrData = ["40-25",null,null,"40-25","50-48",null,"30-25","40-23","50-48","30-25",null,"50-48","40-45","40-45","40-45","40-50","40-50",null,null,null,null,null,"50-48"]
i need to list the same data as below in javascript
var arrDataSorted = ["40-25","50-48","30-25","40-23","40-45","40-50","40-50"]
need only the common data that replicates also the null to be removed.
What is the best solution to solve this.
You can try using Array.prototype.filter() to remove null values and Set to get the unique values. Finally use the Spread syntax (...) to transform the set result into an array.
Try the following way:
var arrData = ["40-25",null,null,"40-25","50-48",null,"30-25","40-23","50-48","30-25",null,"50-48","40-45","40-45","40-45","40-50","40-50",null,null,null,null,null,"50-48"];
var arrDataSorted = [...new Set(arrData.filter(i => i))];
console.log(arrDataSorted);
You can create a set from an array which will automatically remove duplicates:
let arrData = ["40-25",null,null,"40-25","50-48",null,"30-25","40-23","50-48","30-25",null,"50-48","40-45","40-45","40-45","40-50","40-50",null,null,null,null,null,"50-48"];
let set = new Set(arrData);
This will still keep the null, which you can remove with a delete call, and convert back to array with the spread ... operator. The final code will be:
let set = new Set(arrData);
set.delete(null);
let distinctArr = [...set];
add the values into the set if the value is not null and convert it to array.
var arrData = ["40-25",null,null,"40-25","50-48",null,"30-25","40-23","50-48","30-25",null,"50-48","40-45","40-45","40-45","40-50","40-50",null,null,null,null,null,"50-48"];
var setData = new Set();
for(var data of arrData) {
if(data) {
setData.add(data);
}
}
var arrDataSorted = [...setData];
console.log(arrDataSorted);
Add this function to your code:
function removeCommonValues(arr) {
let result = [];
for(let i=0; i < arr.length-1; ++i) {
if(result.includes(arr[i]) === false && arr[i] !== null)
result.push(arr[i])
}
return result
}
Usage:
removeCommonValues(["40-25",null,null,"40-25","50-48",null,"30-25","40-23","50-48","30-25",null,"50-48","40-45","40-45","40-45","40-50","40-50",null,null,null,null,null,"50-48"]) // Return ["40-25", "50-48", "30-25", "40-23", "40-45", "40-50"]
var arrData = ["40-25",null,null,"40-25","50-48",null,"30-25","40-23","50-48","30-25",null,"50-48","40-45","40-45","40-45","40-50","40-50",null,null,null,null,null,"50-48"]
var set = new Set();
for ( var i = 0 ; i< arrData.length;i++ ) {
if(arrData[i]!==null) {
set.add(arrData[i]);
}
}
var newArr = [...set]
You could use array built-in reducer method, in the next code i'm starting with an empty array, and i'm only returning the items that are not null and are not already in the array.
const data = arrData.reduce((state, value) => {
if(value && !state.includes(value)) {
return [...state, value];
}
return state;
}, [])
var arrData = ["40-25",null,null,"40-25","50-48",null,"30-25","40-23","50-48","30-25",null,"50-48","40-45","40-45","40-45","40-50","40-50",null,null,null,null,null,"50-48"]
const output = [];
arrData.forEach(val => {
if(output.indexOf(val) === -1 && val !== null) {
output.push(val);
}
});
console.log(output);
The function can be in a separated file to be reused between multiple pages. Then you can call that function to filter distinct values that are not null.
var arrData = ["40-25",null,null,"40-25","50-48",null,"30-25","40-23","50-48","30-25",null,"50-48","40-45","40-45","40-45","40-50","40-50",null,null,null,null,null,"50-48"];
function fn(value,index,self){
return self.indexOf(value) === index && value;
}
console.log(arrData.filter(fn));
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 a string:
var rrule = "DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1";
I want to convert this string to key-> value pairs in an array.
[
dtstart: 20190514T111500Z,
freq: daily,
interval: 1
]
I know I can take the string and split it based on the semicolon:
var array = rrule.split(";");
... but this leaves me with an array like this:
[
"DTSTART=20190514T111500Z",
"FREQ=DAILY",
"INTERVAL=1"
]
I guess I need another step to map out the keys/values, but I get lost at this point.
Ideally, for the string I want to be able to easily access what dtstarts equals, what interval equals, what other variables equal and so on.
let str = "DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1";
let obj = {};
for (let entry of str.split(";")) {
let pair = entry.split("=");
obj[pair[0]] = pair[1];
}
console.log(obj);
You already know how to split on the ; to get an array, from there you can just aggregate (using reduce) to get an object:
var rrule = "DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1";
var result = rrule.split(";").reduce( (obj,item) => {
let [key,value] = item.split("=");
obj[key] = value;
return obj;
},{});
console.log(result["DTSTART"])
console.log(result["FREQ"])
console.log(result["INTERVAL"])
You were correct to start with split first, this would then return you an array of strings.
To easily convert them, just use map, to return the split the single strings once more, and then return an object based on the property name you would like to give it and it's value
function createKeyValuePairFromString( str ) {
return str.split(';').map( item => {
const splitted = item.split('=');
return { [splitted[0]]: splitted[1] };
});
}
console.log( createKeyValuePairFromString("DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1") );
Use array created and split it again with =
function convertToObject(cookieString) {
const cookieObj = {};
if (!cookieString && typeof cookieString !== 'string') return cookieObj;
const arr = cookieString.split(';');
arr.forEach(record => {
if (record.includes('=')) {
const [key, value] = record.split('=');
cookieObj[key.trim()] = value;
}
});
return cookieObj;
}
You can use it like the code below:
var rrule = "DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1";
let finalObj = {};
rrule.split(';').forEach(i => finalObj[i.split('=')[0]] = i.split('=')[1]);
console.log('finalObj',finalObj);
Here I'm first splitting with ';' so consider the first item to be DTSTART=20190514T111500Z Then on splitting with = I get finalObject['DTSTART'] = 20190514T111500Z
Using forEach()
let str = "DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1";
let obj = {};
let strArr = str.split(';')
strArr.forEach((str) => {
let [key, value] = str.split('=')
obj[key] = value;
});
console.log(obj);
Here's a fairly simple version, returning an object, not an array:
const toObj = str => str
.split (';')
.map ( s => s .split ('=') )
.reduce ( (a, [k, v]) => ({...a, [k]: v}), {} )
let str = "DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1";
console.log (
toObj(str)
)
One of the reasons I like the library is that we can write this sort of logic more simply. In Ramda (disclaimer: I'm one of the authors), it might look like this:
const toObj = pipe ( split (';'), map (split ('=') ), fromPairs)
let str = "DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1";
console.log (
toObj(str)
)
<script src="https://bundle.run/ramda#0.26.1"></script><script>
const {pipe, split, map, fromPairs} = ramda; </script>
var str = "DTSTART=20190514T111500Z;FREQ=DAILY;INTERVAL=1";
// string splitting rule
const rule = (string, delimiter) => string.split(delimiter);
const result = rule(str, ';').reduce((acc, s) => {
const [key, value] = rule(s, '=');
acc[key] = value;
return acc;
}, {});
console.log(result);
I have an array with X number of items. Each has variables separated by a pipe character. In a loop I can split on the pipe to get the second item; but how do I splice to remove the duplicate.
"Sometext|22621086|address|333629dc87894a7ea7df5291fa6d1836|PC_E|1803"
"Sometext2|22622138|working|d3e70175ffe942568cd21f1cf96f4d63|PC_E|1803"
"Sometext3|22622138|working|851946e6325445da99c113951590f714|PC_E|1803"
Results should be this.
"Sometext|22621086|address|333629dc87894a7ea7df5291fa6d1836|PC_E|1803"
"Sometext2|22622138|working|d3e70175ffe942568cd21f1cf96f4d63|PC_E|1803"
Note that the duplicate 22622138 is a random number so the solution needs to work for any number in this location (it's always in the arr[1] position).
This is what I tried:
$.each(arr_transcript, function (i, e) {
if (e.length != 0) {
var arr = e.split("|")
var i = arr_transcript.indexOf(arr[1]);
if (i != -1) {
arr_transcript.splice(i, 1);
}
}
});
Here's a generic function:
function uniqBy(a, key) {
let seen = new Set();
return a.filter(item => {
let k = key(item);
return !seen.has(k) && seen.add(k);
});
};
var data = [
"Sometext|22621086|address|333629dc87894a7ea7df5291fa6d1836|PC_E|1803",
"Sometext2|22622138|working|d3e70175ffe942568cd21f1cf96f4d63|PC_E|1803",
"Sometext3|22622138|working|851946e6325445da99c113951590f714|PC_E|1803"
];
var result = uniqBy(data, item => item.split('|')[1]);
console.log(result)
See here for more info.
Create a map of the numbers you want to check against, and then filter based on that
var arr_transcript = [
"Sometext|22621086|address|333629dc87894a7ea7df5291fa6d1836|PC_E|1803",
"Sometext2|22622138|working|d3e70175ffe942568cd21f1cf96f4d63|PC_E|1803",
"Sometext3|22622138|working|851946e6325445da99c113951590f714|PC_E|1803"
];
var map = arr_transcript.map(function(text) {
return text.split('|')[1];
});
var filtered = arr_transcript.filter(function(item, index) {
return index === map.lastIndexOf( map[index] );
});
console.log(filtered)