How to remove extra occurrences of a reference array - javascript

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);

Related

How to break lines in javascript using .join

I have 9 strings "a", "b", "c", "d", "e", "f", "g", "h", "i" in a JavaScript array.
const arr = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
I am printing the value of arr using JavaScript alert box.
but, if I use arr.join(" ") it is expected like:
a b c d e f g h i
but, I want to change the line for every 3rd element.
like:
a b c
d e f
g h i
How can I do this?
You can use a for loop with Array#slice.
const arr = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
const parts = [];
for(let i = 0; i < arr.length; i += 3){
parts.push(arr.slice(i, i + 3).join(' '));
}
console.log(parts.join('\n'));
This is what I use to chunk arrays:
const chunkSize = 3;
array
.map((_, i) =>
i % itemsPerPage
? undefined
: items.slice(
i,
Math.floor(i / chunkSize) * chunkSize + chunkSize
)
)
.filter(($) => !!$);
So chunk it up and use:
chunkedArray.map((array) => array.join(" ")).join("\n");
The .map used changes all the arrays inside to a b c and then join all of them with a newline character :)
You can also do that with join by using template literal. e.g:
var arr = ["P613221", "W123456", "ew76879", "GDG767"]
var stringWithQuotes = `'${arr.join(`', '`)}'`
console.log({
stringWithQuotes,
query: `SELECT * FROM users WHERE id IN (${stringWithQuotes})`
})
output:
"P613221', 'W123456', 'ew76879', 'GDG767"

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.

How to get the max number and key

I have has like this
var hash = {};
hash['a'] = ["a", "b", "c", "d", "e"];
hash['b'] = ["a", "b", "c"];
hash['k'] = ["q", "b"];
Math.max(Object.keys(hash)
.map(function(key) {
return hash[key].length;
})
)
It returns 5 but, I want to get the hash key 'a' at the same time.
Is it possible??
Combine Object.entries() and Array.prototype.reduce() to get the key and the elements behind that key (and their length)
var hash = {
a: ["a", "b", "c", "d", "e"]
,b: ["a", "b", "c"]
,k: ["q", "b"]
};
var result = Object.entries(hash)
.reduce((r, c) => r[1].length > c[1].length ? r : c);
console.log(result);
Does this fulfil your requirement?
I have used sort instead of Math.max here to find the maxima
var hash = {};
hash['a'] = ["a", "b", "c", "d", "e"];
hash['b'] = ["a", "b", "c"];
hash['k'] = ["q", "b"];
var result = Object.keys(hash)
.map(function(key) {
return {[key]: hash[key].length};
}).sort(function(a, b){
return a.key > b.key
})[0]
console.log(result);
i have used this approach for your problem:
var hash = {};
hash['a'] = ["a", "b", "c", "d", "e"];
hash['b'] = ["a", "b", "c"];
hash['k'] = ["q", "b"];
var largestInfo = {
key:'',
length:0
}
Object.keys(hash).map(function(key) {
if(hash[key].length > largestInfo.length){
largestInfo.key = key;
largestInfo.length = hash[key].length;
}
return hash[key].length;
});
console.log(largestInfo);

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