How could I find intersections in a string array with a variable number of elements? - javascript

I have a function that receives an array composed of numerical, comma separated strings as input, then finds the intersectional numbers in those strings and returns a string of similarly comma separated numbers, with no spaces, containing those intersections. If there are no intersections between the two elements, the function will return false.
What I want is to optimize the function so that it can work with a string array that may have more than just two elements. Is that possible? If so, could I have some sort of guideline of where to start looking for answers?
Currently, this is what I have.
function LocateIntersection(strArr) {
let arrHalf1 = strArr[0].split(", ");
let arrHalf2 = strArr[1].split(", ");
let interArr = arrHalf1.filter(value => arrHalf2.includes(value));
let result = interArr.join();
if (result) {
return result;
} else {
return false;
}
}

My answer is a little flawed, but it should meet your requirements
function LocateIntersection(strArr) {
const AllArrHalf = strArr.map((value) => value.split(', ')).sort((a, b) => b.length - a.length);
const lastArrHalf = AllArrHalf[AllArrHalf.length - 1];
let interArr = [];
AllArrHalf.forEach((value, index) => {
if (index !== AllArrHalf.length - 1) {
interArr.push(lastArrHalf.filter(value1 => value.includes(value1)))
}
})
if (interArr.length > 1) {
let result = interArr.map(value => value.join(', '));
LocateIntersection(result);
} else if (interArr.length === 1) {
result = interArr.join();
console.log(result);
}
}
LocateIntersection(['a, b, c', 'a, b', 'a, b'])

You can try this.
const intersection = (arr1, arr2) => {
return arr2.filter(element => arr1.includes(element));
}
const getIntersection = (stringArray, prevResult) => {
const array1 = prevResult || stringArray[0].split(', ');
const array2 = stringArray.shift().split(', ');
const result = intersection(array1, array2);
console.log(`result : `, result)
if(result.length > 0 && stringArray.length > 0) {
return getIntersection(stringArray, result);
}
return result;
}
const input = ['1, 2','1, 3, 3, 3','123, 222','1, 1, 1','1','3, 2, 3, 1'];
const result = getIntersection(input);
console.log('final Result:',result);

Related

Return all possible combinations of array with optional strings

Lets say I have an array keys = ["the?", "orange", "van", "s?"], with '?' at the end of strings to represent that it is optional.
I want a function in javascript generateCombinations(keys) that returns the possible combinations such as :
[["orange","van"],["the","orange","van"],["orange","van","s"],["the","orange","van","s"]]
One possible way of removing '?' is to simply do a replace("?',"").
I have a feeling it might require a recursive function, which I am not yet quite strong in. Help is appreciated!
So far I've tried this:
function isOptionalKey(key) {
return key.endsWith('?');
}
function hasOptionalKey(keys) {
return keys.some(isOptionalKey);
}
function stripOptionalSyntax(key) {
return key.endsWith('?') ? key.slice(0, -1) : key;
}
function generateCombinations(keys) {
if (keys.length === 1) {
return keys;
}
const combinations = [];
const startKey = keys[0];
const restKeys = keys.slice(1);
if (hasOptionalKey(restKeys)) {
const restCombinations = isOptionalKey(startKey)
? generateCombinations(restKeys)
: restKeys;
if (isOptionalKey(startKey)) {
combinations.push(restCombinations);
}
combinations.push(
restCombinations.map((c) => [stripOptionalSyntax(startKey), ...c])
);
} else {
if (isOptionalKey(startKey)) {
combinations.push(restKeys);
}
combinations.push([stripOptionalSyntax(startKey), ...restKeys]);
}
return combinations;
}
You could take a recursive approach by using only the first item of the array and stop if the array is empty.
const
getCombinations = array => {
if (!array.length) return [[]];
const
sub = getCombinations(array.slice(1)),
optional = array[0].endsWith('?'),
raw = optional ? array[0].slice(0, -1) : array[0],
temp = sub.map(a => [raw, ...a]);
return optional
? [...temp, ...sub]
: temp;
};
keys = ["the?", "orange", "van", "s?"],
result = getCombinations(keys);
console.log(result.map(a => a.join(' ')));

Find occurance of characters in array of object using js

I have array of object with few words I want to know occurance of each word and push into key value pair format
let words = ["aabbbc", "dddeeef", "gghhhii"]
Output
[{a:2, b:3,c:1}, {d:3,e:3,f:1}, {g:2,h:3:i:2}]
This is a classic map and reduce task where one maps the array of strings and for each string creates the character-specific counter-statistics while reducing the string's character-sequence (...split('').reduce( ... )) and by programmatically building an object which counts/totals each character's occurrence.
console.log(
["aabbbc", "dddeeef", "gghhhii"]
.map(string =>
string
.split('')
.reduce((result, char) => {
result[char] = (result[char] ?? 0) + 1;
return result;
}, {})
)
)
// [{a:2, b:3,c:1}, {d:3,e:3,f:1}, {g:2,h:3:i:2}]
.as-console-wrapper { min-height: 100%!important; top: 0; }
let words = ["aabbbc", "dddeeef", "gghhhii"]
const occurences = (w) => {
const obj = {};
for (const c of w) {
if (obj[c] === undefined) obj[c] = 0;
obj[c]++;
}
return obj;
}
const arr = words.map(w => occurences(w));
console.log(arr)
Trying to keep it easy and readable:
const words = ['aabbbc', 'dddeeef', 'gghhhii']
const output = []
for (const word of words) {
const result = {}
for (const letter of word) {
result[letter] = result[letter] || 0
result[letter]++
}
output.push(result)
}
console.log({ output })
let words = ["aabbbc", "ddeeef", "ghhhii"]
let newArr = []
words.forEach((e,index)=>{
e.split('').forEach(n=>{
if(!newArr[index]){
newArr[index]={}
}
if(!newArr[index][n]){
newArr[index][n]=0
}
(newArr[index][n]>=0) && ++newArr[index][n]
})
})
console.log(newArr)

How to join an n-dimension array with different separators for each level?

Sample input
Array
Here I am showing a 3-dimension array but the actual number of dimensions vary and is known as n.
[
[
[1,2],
[3,4]
],
[
[5,6],
[7,8]
]
]
Separators
It has the same length (n) as the number of dimensions of the array where the i-th element represent the separator of the i-th level of the array.
[',', '_', '-']
Desired output
1-2_3-4,5-6_7-8
What I've tried
It works for a 3-dimension array but not for a 4-dimension one.
I know what is going wrong with my code but I have no idea how to fix it.
Besides, I think there are simpler and/or more efficient methods.
3-dimension (working)
const array = [[[1,2],[3,4]],[[5,6],[7,8]]];
const separators = [',', '_', '-'];
const _separators = separators.reverse();
let i;
function join(array, first = false) {
const next = Array.isArray(array[0]);
let result;
if (next) {
result = array.map(e => {
if (first) { i = 0; }
return join(e);
});
i++;
result = result.join(_separators[i]);
}
else {
result = array.join(_separators[i]);
}
return result;
}
const result = join(array, true);
console.log(result);
4-dimension (not working properly)
const array = [[[[1,2],[3,4]],[[5,6],[7,8]]],[[['A','B'],['C','D']],[['E','F'],['G','H']]]];
const separators = ['|', ',', '_', '-'];
const _separators = separators.reverse();
let i;
function join(array, first = false) {
const next = Array.isArray(array[0]);
let result;
if (next) {
result = array.map(e => {
if (first) { i = 0; }
return join(e);
});
i++;
result = result.join(_separators[i]);
}
else {
result = array.join(_separators[i]);
}
return result;
}
const result = join(array, true);
console.log(result);
// desired output: 1-2_3-4,5-6_7-8|A-B_C-D,E-F_G-H
Something like this with recursion
const join = (array, separators, depth) => {
if (depth < separators.length -1) {
return array.map(el => join(el, separators, depth + 1)).join(separators[depth]);
} else {
return array.join(separators[depth]);
}
};
{
const array = [[[1,2],[3,4]],[[5,6],[7,8]]];
const separators = [',', '_', '-'];
console.log(join(array, separators, 0));
}
{
const array = [[[[1,2],[3,4]],[[5,6],[7,8]]],[[['A','B'],['C','D']],[['E','F'],['G','H']]]];
const separators = ['|', ',', '_', '-'];
console.log(join(array, separators, 0));
}

how to improve this algorithm for combinations?

I have this problem, I need to find a combination with specific numbers, and the sum of the numbers should be a other specific amount, i think that you can understand me with the code.
function get4() {
function iter(temp) {
return function (v) {
var t = temp.concat(v);
if (t.length === 4) {
if (t.reduce(add) === 10) {
result.push(t);
}
return;
}
values.forEach(iter(t));
};
}
const
add = (a, b) => a + b,
values = [1, 2, 3, 4],
result = [];
values.forEach(iter([]));
return result;
}
console.log(get4().map(a => a.join(' ')));
with this code I can find a 4 digits that his sum is 10, with little numbers works, but if a try with bigger numbers, the function crash, I mean, the browser not execute it.
my problema is with this data
length = 493
the sum is = 42990
and the values are = [500,400,300,200,100,90,80,70,60,50,40,30,20,10,5]
how can I improve this code? if you have another solution in other language, it would also help me.
You could:
// comments removed for simplicity
function combinationSumRecursive(
candidates,
remainingSum,
finalCombinations = [],
currentCombination = [],
startFrom = 0,
) {
if (remainingSum < 0) {
return finalCombinations;
}
if (remainingSum === 0) {
finalCombinations.push(currentCombination.slice());
return finalCombinations;
}
for (let candidateIndex = startFrom; candidateIndex < candidates.length; candidateIndex += 1) {
const currentCandidate = candidates[candidateIndex];
currentCombination.push(currentCandidate);
combinationSumRecursive(
candidates,
remainingSum - currentCandidate,
finalCombinations,
currentCombination,
candidateIndex,
);
currentCombination.pop();
}
return finalCombinations;
}
function removesDuplicatesAndNon4Length(arr) {
return arr.map(x => [...new Set(x)]).filter(x => x.length === 4);
}
const tempResp = combinationSumRecursive([1, 2, 3, 4], 10);
const resp = removesDuplicatesAndNon4Length(tempResp);
console.log(resp);
Note: This is a Combination Sum Problem version modificated for this specific program.

Counting letters and numbers in string

I write a code that works with letter but not with numbers
I know it maybe a little complicated but this is how I could do it;
with numbers it produce ordered Array and I don't know why
var orderedCount = function(text) {
let splitted = text.split('');
let countedLetters = splitted.reduce((AllLetters, letter) => {
(letter in AllLetters) ? AllLetters[letter]++: AllLetters[letter] = 1;
return AllLetters
}, {})
let result = Object.keys(countedLetters).map((key) => {
return [(key), countedLetters[key]]
})
return result;
};
console.log(orderedCount("abracadabra")); //[['a',5], ['b',2], ['r',2], ['c',1], ['d',1]]
console.log(orderedCount("212")); //[['1',1], ['2',2]]
[['1',1],['2',2]]
should be
[['2',2],['1',1]]
You can use Object.entries to convert the object into an array and use sort to sort the element 1
var orderedCount = function(text) {
let splitted = text.split('');
let countedLetters = splitted.reduce((AllLetters, letter) => {
(letter in AllLetters) ? AllLetters[letter]++: AllLetters[letter] = 1;
return AllLetters
}, {})
let result = Object.entries(countedLetters).sort((a, b) => {
return b[1] - a[1];
})
return result
};
console.log(orderedCount("abracadabra"));
console.log(orderedCount("212"));
Shorter Version:
var orderedCount = function(text) {
return Object.entries(text.split('').reduce((c, v) => {
c[v] = (c[v] || 0) + 1;
return c;
}, {})).sort((a, b) => b[1] - a[1]);
};
console.log(orderedCount("abracadabra"));
console.log(orderedCount("212"));
You can create the array directly using Array#reduce method where use a reference object which keeps object reference based on letter value.
var orderedCount = function(text) {
const ref = {};
return text.split('').reduce((arr, letter) => {
(letter in ref) ? ref[letter][1]++: arr.push(ref[letter] = [letter, 1]);
return arr;
}, []);
};
console.log(orderedCount("abracadabra")); //[['a',5], ['b',2], ['r',2], ['c',1], ['d',1]]
console.log(orderedCount("212")); //[['1',1], ['2',2]]
Refer : Does JavaScript Guarantee Object Property Order?
Since es2015 onwards non-integer keys are kept inserting order and integer keys are sorted numerically.
You need to sort you result by count, because by default numeric keys in Object will be in ascending order
var orderedCount = function(text) {
let splitted = text.split('');
let countedLetters = splitted.reduce((AllLetters, letter) => {
(letter in AllLetters) ? AllLetters[letter]++: AllLetters[letter] = 1;
return AllLetters
}, {})
let result = Object.keys(countedLetters).map((key) => {
return [(key), countedLetters[key]]
})
return result.sort((a,b)=>b[1] - a[1]);
};
console.log(orderedCount("abracadabra")); //[['a',5], ['b',2], ['r',2], ['c',1], ['d',1]]
console.log(orderedCount("212")); //[['1',1], ['2',2]]

Categories