Converting number string into number in an array - javascript

I have an array containing single strings. e.g. ["a", "b", "3", "c"];
However, I need any number in this array to be a number and not a string.
Result would be ["a", "b", 3, "c"]; so I could then run a regex and get all numbers out of the array.
Hope this is clear enough.

You can use map and isNaN
let a = ["a", "b", "3", "c"];
let final = a.map(val => !isNaN(val) ? +val : val)
console.log(final)

You could use + since NaN is evaluated as false if the value is not a number, so (+e || e) returns a number or the original value:
const array = ["a", "b", "3", "c"];
const res = array.map(e=>(+e || e));
console.log(res);

Related

How do i write a function that iterates through a list of sets of elements of varied amounts extracting sequential arrays of 4

i have a long list of sets of elements of varied amounts . For each line, I want to extract only those sets which have 4 elements or more and push them into a separate array . If the set has more than 4 elements , I want to extract each set of 4 elements within them. for instance
a,b,c
a,b,c,d
d,b,c,a
a,b,d,c,a,d
a,d
returns
result = [ [a,b,c,d], [d,b,c,a] , [a,b,d,c], [b,d,c,a], [d,c,a,d] ]
notice that the second to the last set of elements produces 3 arrays at the end of the result array.
How would i write a JS or Ruby function/method to return this kind of result ??
A Ruby solution: first select the arrays which are big enough, then put all consecutive series of 4 elements in the result.
input = [['a','b','c'], ['a','b','c','d'], ['d','b','c','a'], ['a','b','d','c','a','d'], ['a','d']]
p input.select{|ar| ar.size >= 4}.flat_map{|ar| ar.each_cons(4).to_a }
# =>[["a", "b", "c", "d"], ["d", "b", "c", "a"], ["a", "b", "d", "c"], ["b", "d", "c", "a"], ["d", "c", "a", "d"]]
Here is the solution, I looked at the array if it is length of 4 I just pushed it into the result if it is more then 4 then I iterated over it to push every one instance of 4, I hope this is what you wanted.
const input = [['a','b','c'], ['a','b','c','d'], ['d','b','c','a'], ['a','b','d','c','a','d'], ['a','d']]
const result = []
input.forEach(arr => {
if (arr.length === 4) {
result.push(arr)
} else if (arr.length > 4) {
for (let i = 0; i < arr.length - 3; i++) {
result.push(arr.slice(0 + i, 4 + i))
}
}
})
console.log('result = ', result)
//result = [ [a,b,c,d], [d,b,c,a] , [a,b,d,c], [b,d,c,a], [d,c,a,d] ]
Another Ruby solution.
input = [['a','b','c'], ['a','b','c','d'], ['d','b','c','a'],
['a','b','d','c','a','d'], ['a','d']]
input.each_with_object([]) do |a,arr|
a.each_cons(4) { |a4| arr << a4 } if a.size > 3
end
#=> [["a", "b", "c", "d"], ["d", "b", "c", "a"], ["a", "b", "d", "c"],
# ["b", "d", "c", "a"], ["d", "c", "a", "d"]]
See Enumerable#each_cons.

Google Apps Script: Find the location of every item in array

I would like to run through every item in a 1D array and perform an indexOf on another 1D array to determine where it matches.
If I have:
Array 1 = ["a","d","e"]
Array 2 = ["a","b","c","d","e","f"]
I would like to transform Array 1 from values into match locations where it would become: [0,3,4].
I tried the equation below, but it didn't work. I thought using forEach() I could go through every item in Array 1. Then I could run a function to perform an indexOf() on Array 2 for each item. What am I doing wrong??
var array1 = ["a","d","e"];
var array2 = ["a","b","c","d","e","f"];
var array1count = array1.forEach( function (e) { array2.indexOf( e )});
Logger.log(array1count)
If array1 has the same order as array2, you could take a closure over the index and use a while loop inside of the callback for mapping found indices.
var array1 = ["a", "d", "e"],
array2 = ["a", "b", "c", "d", "e", "f"],
indices = array1.map((i => v => {
while (array2[++i] !== v) ;
return i;
})(-1));
console.log(indices); // [0, 3, 4]
For not defined order, you neeeither a single loop for gathering the indices and another to map the collected indices.
var array1 = ["a", "d", "e"],
array2 = ["a", "b", "c", "d", "e", "f"],
indices = array1.map(
Map.prototype.get,
array2.reduce((m, v, i) => m.set(v, i), new Map)
);
console.log(indices); // [0, 3, 4]
forEach() returns undefined, you can try using Array.prototype.reduce():
The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.
var array1 = ["a","d","e"];
var array2 = ["a","b","c","d","e","f"];
var array1count = array2.reduce(function(acc, curr, i) {
if(array1.includes(curr)) //check if the current item is present in array1
acc.push(i);
return acc;
},[]);
console.log(array1count);
I ran this equation and it worked. Seems to be pretty simple and straightforward. Hopefully I'm not missing something here that the other answers are resolving.
var array1 = ["a","d","e"];
var array2 = ["a","b","c","d","e","f"];
var array1count = array1.map( function (item) { return array2.indexOf(item) });
Logger.log(array1count)

How to remove extra occurrences of a reference array

let's assume that we have two arrays like these:
let s1 =  ["A", "B", "C", "D", "B"] // Note: "B" has been occurred 2 times
let s2 = ["A", "B", "C", "D", "B", "A", "X", "Y"] // // Note: "B" has been occurred 2 times just like s1 but we have another occurrence for "A"
I want to create a new array (let s3) based on these two arrays with this rule that we'll remove the element(s) with occurrences more than the same element's occurrence in array s1
so the s3 array would be like this:
let s3 = ["A", "B", "C", "D", "B", "X", "Y"] // we just removed "A" cause it occurred more than "A" occurances in s1
Note that we want anything else ("X", "Y"). we just want to handle the extra occurrences.
so far I can find the index of repeated occurrences like this but I can't find a way to compare each occurrence to see if it is an extra one or not (complicated):
let s1 =  ["A", "B", "C", "D", "B"]
let s2 = ["A", "B", "C", "D", "B", "A", "X", "Y"]
var s3 = [];
for (let i = 0; i < s2.length; i++) {
for (let j = 0; j < s1.length; j++) {
if (s2[i] === s1[j]) {
s3.push(i);
break;
}
}
}
console.log(s3)
My English is poor and I don't know if I could explain the issue or not!
Note: I can simply use s3 = [...new Set(s2)] to remove repeated elements but I want something else.
Since you want to keep everything originally in s1 but only add items from s2 if they aren't already in you can initially set s3 to s1. Then loop over s2 and if s1 does not have the value then push it into s3.
const s1 = ["A", "B", "C", "D", "B"];
const s2 = ["A", "B", "C", "D", "B", "A", "X", "Y"];
const s3 = [...s1];
s2.forEach(d => {
if (!s1.includes(d)) s3.push(d);
});
console.log(s3);
You can use Map and filter
First Map the array1 to [key, value] format
Iterate over second array, if it's found in Map and value is grater than zero return true else return false,
If it is not found return true
let s1 =  ["A", "B", "C", "D", "B"]
let s2 = ["A", "B", "C", "D", "B", "A", "X", "Y"]
let map = new Map()
s1.forEach(v=>{
if(map.has(v)){
map.set(v,map.get(v)+1)
} else{
map.set(v,1)
}
})
let final = s2.filter(val=>{
if(map.has(val)){
if(map.get(val)){
map.set(val, map.get(val)-1)
return true
}
return false
}
return true
})
console.log(final)
You could count the values of the first set and return the values for a given count or if not known then all items.
var s1 = ["A", "B", "C", "D", "B"],
s2 = ["A", "B", "C", "D", "B", "A", "X", "Y"],
count = s1.reduce((m, v) => m.set(v, (m.get(v) || 0) + 1), new Map),
s3 = s2.filter(v => count.get(v) ? count.set(v, count.get(v) - 1) : !count.has(v));
console.log(...s3);

How to pop an element in array in javascript?

How can I pop the random chosen out of the array?
var number = ["a", "b", "c"];
var random = number[Math.floor(Math.random()*number.length)];
use splice
var number = ["a", "b", "c"];
var random = Math.floor(Math.random()*number.length);
console.log(number[random], ' is chosen');
var taken = number.splice(random, 1);
console.log('after removed, ', number);
console.log('number taken, ', taken);
Use splice and the random number as the index.
number.splice(random, 1);
You can use Splice to remove a certain number of items from an array. This method will altar the original array and return the values removed.
The first argument in the Splice method is the starting point. The second argument is the number of items to remove.
Example:
// 0 1 2
var array = ["a", "b", "c"];
var splicedItem = array.splice(1,1);
// The array variable now equals ["a", "c"]
console.log("New Array Value: " + array);
// And the method returned the removed item "b"
console.log("Spliced Item: " + splicedItem);
You can also use a negative number in the first argument to begin counting backwards from the end of the Array.
Example:
// -6 -5 -4 -3 -2 -1
var array2 = ["a", "b", "c", "d", "e", "f"];
var splicedItem2 = array2.splice(-3, 2);
// The array2 variable now equals ["a", "b", "c", "f"]
console.log("New Array Value: " + array2);
// The values removed were "d" and "e"
console.log("Spliced Item: " + splicedItem2);
You can even insert new items into the Array by including additional arguments. You also don't need to return the spliced items to a new variable if you don't want to.
Example:
var array3 = ["a", "b", "c", "d", "e", "f"];
array3.splice(2, 2, "Pink", "Mangoes");
// The array3 value is now ["a", "b", "Pink", "Mangoes", "e", "f"]
console.log("New Array Value: " + array3);

Pull array values associated with bitmask

I have a simple bitmask, 3 ("011" in base 2) which denotes that I should extract array[0] and array[1] but not array[2]
What is an efficient way to do this?
Ultimately, I'm generating a new array with values that passed a .filter
Something like this:
var bitmask = 37, // "100101"
array = ["a", "b", "c", "d", "e", "f"];
var array2 = array.filter((value, index) => {
// do something with bitmask and index to return true
});
// array2 should be ["a", "c", "f"];
Expanding on your original example you can do this:
var bitmask = 37, // "100101"
array = ["a", "b", "c", "d", "e", "f"];
var array2 = array.filter((value, index) => {
// do something with bitmask and index to return true
return bitmask & (1 << index);
});
// array2 should be ["a", "c", "f"];
console.log(array2);
var bitmask = 5, idx=0;
// Loop till bitmask reach 0, works when bitmask >= 0
// If you want to sure instead of implicit type converting (from number to boolean)
// Just change it to while(bitmask >= 0)
while(bitmask){
// If the rightmost bit is 1, take the array[index]
if(bitmask & 1) console.log("take arr["+idx+"]");
// Shift right by 1 bit, say 5 = 101, this will make the number become 2 = 10
bitmask>>=1;
// Increase the index
idx++;
}
Using your own example, here is the code works:
var bitmask = 37, // "100101"
array = ["a", "b", "c", "d", "e", "f"],
idx = 0;
var array2 = [];
while(bitmask){
if(bitmask & 1) array2.push(array[idx]);
bitmask>>=1;
idx++;
}
Simply use some bit operation to loop it. As it is looping bit by bit, I think it is the fastest you can get
One way to do this is cast your number into a binary string, then check if the index of the bitmask is "1" inside your filter.
var bitmask = (37).toString(2), // "100101"
array = ["a", "b", "c", "d", "e", "f"];
var array2 = array.filter((value, index) => {
if(bitmask[index] == "1") return value;
});
console.log(array2);

Categories