I'm trying to get the values from an array so I can filter them.
Using hints from
Add single quotes in a string array javascript but it doesn't return the whole array with quotes around each value.
Tried:
var ages = Array.from({ length: 5 }, (_x, i) => i + 1);
console.log(ages); // [1,2,3,4,5]
ages = ages.toString();
console.log(ages); // "1,2,3,4,5"
const newArr = ages[0].split(",").map(x => x.trim());
console.log(newArr); // ["1"]
//desired: ["1","2","3","4","5",] or ["1","2","3","4","5"]
You are over-complicating this, particularly by first converting the entire array with toString(). It's as simple as follows:
const ages = Array.from({ length: 5 }, (_x, i) => i + 1);
const newArr = ages.map(age => age.toString());
console.log(newArr); // [ '1', '2', '3', '4', '5' ]
Related
I have a array1 from checkboxes selected, and i need to compare with the most similar, how i do that?
var array1 = ["pain", "fever", "vomit"]
var array2 = ["diarrhea", "fever", "vomit", "embolism", "bleeding"]
var array3 = ["diarrhea", "tumor", "vomit", "cold", "bleeding"]
I tried some methods but they only return me as "true" or "false", I would like to get the most similar array1
You could count the number of similar elements using reduce, then order your arrays by similarity and take the first element:
const array1 = ["pain", "fever", "vomit"];
const array2 = ["diarrhea", "fever", "vomit", "embolism", "bleeding"];
const array3 = ["diarrhea", "tumor", "vomit", "cold", "bleeding"];
const countSimilarElements = (arr1, arr2) => arr1.reduce((count, x) => count + arr2.includes(x), 0);
const orderBySimilarity = (arr1, ...arr) =>
arr.map(x => ({ array: x, similarity: countSimilarElements(arr1, x) }))
.sort((a, b) => b.similarity - a.similarity);
const ordered = orderBySimilarity(array1, array2, array3);
console.log(ordered);
console.log(ordered[0].array);
This function takes in a the array you want to compare as the 'base' and a list of other arrays as 'arr_list', then returns a similarity array showing how similar each array in 'arr_list' was to the 'base'. This way you can compare multiple arrays with a single call and know reference their similarity by referencing the index of the returned similarity array.
const a = ['11', '22', '33'], b = ['11', '44', '55', '66'], c = ['55', '33', '11', '22'], d = ['11', '66', '44', '22'];
const Similarity = (base, arr_list) => {
let similarity = new Array(arr_list.length).fill(0);//creates similarity array which defaults to 0
base.forEach( el => {
arr_list.forEach( (arr, i) => similarity[i] += arr.includes(el) )
});
return similarity;
}
const similarity = Similarity(a, [b,c,d])
console.log(similarity)
I'm trying to double each element in an array
let arr = ['onions', 'tomatoes', 'etc'...';
with a for loop and keep getting NaN error... I'm still learning so any advice would be appreciated.
I've tried for loop, .map(), and other methods, but just can't see the obvious problem...
let newIngr = tortSoup.filter(function(value, index, arr) {
if (value !== 'onion' && value !== 'red pepper') {
return value;
console.log(newIngr);
});
}
let myReci = [];
for(var i = 0; i < newIngr.length; i++) {
myReci[i] = newIngr[i] * 2;
}
console.log(myReci);
Expected: each array element multiped by two and returned:
['onions', tomatoes', 'garlic', 'fontina']
would become:
['onions', 'onions', 'tomoatoes', 'tomatoes', garlic, 'garlic', 'fontina', 'fontina']
Here is a way to do it with Array.reduce() and the spread operator:
const array = ['onions', 'tomatoes', 'garlic', 'fontina'];
const result = array.reduce((acc, x) => ([...acc, x, x]), []);
console.log(result)
Array.reduce iterates over your input array and calls the callback for each element. This callback is given two arguments, the first is the output from the last iteration, and the second one is the current array item.
The callback here returns a new array composed of the previous result of the callback (spread into the new array with the spread operator ...) and the current item repeated twice.
To start the reducing process, we also need an initial value, here we give an empty array, (last argument to reduce).
Here is a detailed description of the values of acc and x in the callback for the following reduction:
['a', 'b', 'c'].reduce((acc, x) => ([...acc, x, x]), []);
acc = [], x = 'a' => returns ['a', 'a']
acc = ['a', 'a'], x = 'b' => returns ['a', 'a', 'b', 'b']
acc = ['a', 'a', 'b', 'b'], x = 'c' => returns ['a', 'a', 'b', 'b', 'c', 'c']
Iterate over input array using .map().
Initialize new array using Array() constructor and filling it using .fill() method of arrays.
Finally you can convert array of arrays to a single array using .concat() and spread operator.
const input = ['onions', 'tomatoes', 'garlic', 'fontina'];
const dupeValues = (arr, factor) => [].concat(...arr.map(s => new Array(factor).fill(s)));
console.log(dupeValues(input, 2));
console.log(dupeValues(input, 3));
Use Array.flatMap() (not supported by IE/Edge):
const array = ['onions', 'tomatoes', 'garlic', 'fontina'];
const result = array.flatMap(item => [item, item]);
console.log(result)
Using vanilla JavaScript :
const ingredients = [ 'onions', 'tomatoes', 'garlic', 'fontina' ]
const ingredientsToRemove = [ 'onions', 'red pepper' ]
// Using Array.reduce method
const doubleIngredients = ingredients.reduce(
( array, ingredient ) =>
{
// If the ingredient has to be removed, return the array
// Else return the array with two times the current ingredient
return ingredientsToRemove.includes( ingredient ) ?
array
:
[ ...array, ingredient, ingredient ]
},
[]
)
console.log({ ingredients, doubleIngredients })
Well the problem here is
string * 2 will not return 2 strings to you. it will return NaN
console.log('test'* 2) //NaN
What you're trying to achieve can be done by repeat method.
console.log('test '.repeat(2))
Your expected output can be achieved like this
let arr = ['onions', 'tomatoes', 'garlic', 'fontina']
let output = arr.reduce((op,inp)=>(op.concat([inp,inp])),[])
console.log(output)
i would like to split an array into multiple chunks but applying a function to it to decide how to create the chunks.
For example, if i have an array of letters, numbers or letters and numbers, apply a function to the array to split it into array of arrays of the previous categories.
let arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3']
myChunkFunction(arr, myCustomSplitFunction)
// result
[['a','b','c'], ['1','2','3'], ['a1', 'a2','a3']]
Lodash has a chunk function but it splits into n chunks, also array has a slice function but you need to specify the begin and the end so how could i split with a custom function.
Try doing this
let arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3']
const splitFn = (str) => Number.isInteger(+str) ? 0 : str.length == 1 ? 1 : 2
const myChunkFunction = (arr, fn) => arr.reduce((r,c) => {
let t = fn(c)
r[t] = [...r[t], c]
return r
}, [[],[],[]])
console.log(myChunkFunction(arr, splitFn))
Hint
The key to the answer is to, somehow, reorganize the source array such that all the elements with the same key will be in the same place.
The easiest way I can think to solve it is by using hash-map. Each element in the hash-map will be a different array containing all the elements with the same key.
Try it for your self before you keep reading and see the full solution.
The implementation
As you can see, I solved it as functional as possible. To avoid mutations, I used reduce to iterate over the source array and put each element in the hashmap (by generating a key from the element).
I recreate the final hash-map over and over using shallow copy. Finally, I convert the hash-map to an array of array (because that was your demand) using Object.values
const splitArrayByKey = extractKey => array => {
const arraysByKey_obj = array.reduce((hashMapOfArrays,element)=> {
const key = extractKey(element);
// if we already added an element with the same key,
// then we add the current element to there.
// else, we create a new key and put the current element there.
if(hashMapOfArrays.hasOwnProperty(key))
return {
...hashMapOfArrays,
[key]: [...hashMapOfArrays[key],element]
};
return {
...hashMapOfArrays,
[key]: [element]
};
},{});
// transform the arraysByKey_obj to an array of arrays:
return Object.values(arraysByKey_obj);
};
// example 1:
const result1 = splitArrayByKey(element=>element)([1,2,3,1,2,3]);
console.log(result1);
console.log('------------------');
// example 2:
const result2 = splitArrayByKey(element=>element.id)([{id:1,x:1},{id:{},x:2},{id:"id",x:3},{id:1,x:4}]);
console.log(result2);
Here is a way to do this via ES6:
let arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3']
const splitFn = (str) => Number.isInteger(+str) ? 0 : str.length == 1 ? 1 : 2
const myChunkFunction = (arr, fn) => arr.reduce((r,c) => {
let t = fn(c)
r[t] = [...r[t], c]
return r
}, [[],[],[]])
console.log(myChunkFunction(arr, splitFn))
The typeFn plays the role of filtering the elements to number, string with 1 length and other. That output is used by the myChunkFunction to place the element in the right array.
You could do something like this with less control and in one line with reduce and ES6 array spread:
let arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3']
const result = arr.reduce((r,c) =>
(Number.isInteger(+c) ? r[0] = [...r[0], c] :
c.length == 1 ? r[1] = [...r[1], c] : r[2] = [...r[2], c], r), [[],[],[]])
console.log(result)
You start with [[],[],[]] and fill each of the sub arrays based on number, length of the string == 1, other lenghts.
You could wrap that in a function.
const arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3'];
const getClassification = function(x){
const hasNumber = x.split('').some(x => parseFloat(x));
const hasChar = x.split('').some(x => !parseFloat(x));
if(!parseFloat(x) && (!hasNumber && hasChar)) return 0;
else if(parseFloat(x)) return 1;
else return 2;
}
const myChunkFunction = function(arr, classifier){
let jaggedArray = [[], [], []];
arr.forEach(x => {
jaggedArray[classifier(x)].push(x);
})
return jaggedArray;
}
console.log(myChunkFunction(arr, getClassification));
I think this satisfies.
I am looking for a JavaScript function which accepts two string arrays of equal length and outputs a single string array which is the same length as the input arrays, containing the element-wise-concatenated strings of the input arrays. Is there a built-in JavaScript function which does this?
Additionally, I would like to add in a string between the concatenated elements when the element-wise concatenation is done. For example, so that this would be true for each i:
outputArray[i] = inputArray1[i] + " - " + inputArray2[i]
You could reduce an array with the single arrays. This works for more than one array as well.
var inputArray1 = ['abc', 'def', 'ghi'],
inputArray2 = ['3', '6', '9'],
outputArray = [inputArray1, inputArray2].reduce((a, b) => a.map((v, i) => v + ' - ' + b[i]));
console.log(outputArray);
More functional
var inputArray1 = ['abc', 'def', 'ghi'],
inputArray2 = ['3', '6', '9'],
outputArray = [inputArray1, inputArray2]
.reduce((a, b) => a.map((v, i) => [].concat(v, b[i]))) // get single parts
.map(a => a.join(' - ')); // join inner arrays
console.log(outputArray);
I have two arrays, of which the Remove should be removed from the List, and the number removed should be counted.
I'm using this to remove those from 'Remove':
let output=this.List.filter((el)=>{
return this.Remove.indexOf(el) <0;
})
This is working fine, but I'd like to count the number of items that have overlapped, and thus been removed in the filter.
For example, if List=['1','2','3','4','5'] and Remove=['1','4'], count would be 2.
Many thanks!
You can do this in one reduce run. For example, you can create an object and track both cleared array and a number of deleted elements:
const a = [1,2,3,4,5,6,7];
const b = [1,4,9]; // elements to remove
const c = a.reduce((acc, cur) => b.includes(cur)
? Object.assign(acc, {n: acc.n + 1})
: Object.assign(acc, {res: acc.res.concat(cur)}), { n: 0, res: []});
console.log(c)
If you don't want to compare lengths as suggested in comments (which is fine...), I can propose you the following solution using a counter:
let list = ['1', '2', '3', '4', '5'],
remove = ['1', '4'],
overlap = 0;
let output = list.filter(el => {
let bool = remove.indexOf(el) < 0;
if (!bool) overlap++;
return bool;
});
console.log(overlap);
Assuming all the items in the arrays a and b are unique, you can make use of Sets to get the absolute number of intersections as a one-liner:
const a = [1,2,3,4];
const b = [2,4,5];
const overlap = a.length + b.length - new Set(a.concat(b)).size; // => 2