compare 2 arrays and check the positions - javascript

I have 2 arrays, one has 10 elements and the other one 3, I need to create a new array with the same size of the biggest vector, with a boolean checking true in the position where exist some element from the array of 3 elements
I have the following arrays
array1 = [1,2,3,4,5,6,7,8,9,10]
array2 = [4,6,10]
I tried making 2 for loops
for(var i=0; i<array1.lenght; i++){
for(var j=0; i<array2.lenght; i++){
if(array1[i]==array2[j]){
array3.push(true)
}else{
array3.push(false)
}
}
}
the vector that I need would be
array3 = [false, false, false, true, false, true, false, false, false, true]

You can forEach first array and use include method to check if item existed in array as
let array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let array2 = [4, 6, 10];
let array3 = [];
array1.forEach(function (c) {
if (array2.includes(c)) {
array3.push(true)
} else {
array3.push(false);
}
})
console.log(array3)

Use map like so with shift like so:
const array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const array2 = [4, 6, 10];
const array3 = array1.map(e => {
if (array2[0] == e) {
array2.shift();
return true;
}
return false;
});
console.log(array3);
.as-console-wrapper { max-height: 100% !important; top: auto; }
If you just want a basic check as for whether the element is in the array, not the order, then use includes.
const array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const array2 = [4, 6, 10];
const array3 = array1.map(e => array2.includes(e));
console.log(array3);
.as-console-wrapper { max-height: 100% !important; top: auto; }

You can also instead of another array use a Set and then Array.map the first away checking if the value is in the Set:
let array1 = [1,2,3,4,5,6,7,8,9,10],
set = new Set([4,6,10])
let result = array1.map(x => set.has(x))
console.log(result)

I would suggest to keep things simple and to use Array#indexOf method to determine if array contains another element.
const array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const array2 = [4, 6, 10];
const b = array1.map(el => {
return array2.indexOf(el) !== -1;
});
console.log(b);

const array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const array2 = [4, 6, 10];
const finalArray = [];
for (let data of array1) {
finalArray.push(array2.includes(data));
}

Related

How object hash works to remove duplicates in this scenario?

function distinctUnion(arr, arr2) {
let merged = [...arr, ...arr2];
var result = [];
var map = {}
for (let i = 0; i < merged.length; i++) {
if (!map.hasOwnProperty(merged[i])) {
map[merged[i]] = true; // Line 3 --> if I remove this line, it prints duplicates
console.log('map', JSON.stringify(map, 2, null));
result.push(merged[i]);
}
}
return result;
}
let arr = [3, 4, 5, 6, 6, 4, 5, 8, 9, 10, 10];
let arr2 = [11, 11, 11, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6];
console.log('unique ', JSON.stringify(distinctUnion(arr, arr2), 2, null));
All we are setting here is map[merged[i]] = true; for all keys in object
map {"3":true,"4":true,"5":true,"6":true,"8":true,"9":true,"10":true,"11":true}
then how result.push(merged[i]) has only unique values?
I mean to say merged[i] inside loop should still have all array values including duplicates right?
I am not able to understand the link between map[merged[i]] = true; and result.push(merged[i])
If you do not set the property to anything, map.hasOwnProperty(...) will spuriously return false for the next time that value is encountered, thus allowing duplicates. You don't need to set it to true, as it is just used to indicate the presence of a key; any value is fineā€”even undefined!
function distinctUnion(arr, arr2) {
let merged = [...arr, ...arr2];
var result = [];
var map = {}
for (let i = 0; i < merged.length; i++) {
if (!map.hasOwnProperty(merged[i])) {
map[merged[i]] = undefined;
result.push(merged[i]);
}
}
return result;
}
let arr = [3, 4, 5, 6, 6, 4, 5, 8, 9, 10, 10];
let arr2 = [11, 11, 11, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6];
console.log('unique ', JSON.stringify(distinctUnion(arr, arr2), 2, null));
To make your code works, you just need to replace map[merged[i]] = true; with map[merged[i]] = undefined;.
However, you can make your function more simplified as follows:
function distinctUnion(arr, arr2) {
let map = {};
[...arr, ...arr2].forEach((x)=>{map[x] = x});
return Object.values(map);;
}
let arr = [3, 4, 5, 6, 6, 4, 5, 8, 9, 10, 10];
let arr2 = [11, 11, 11, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6];
console.log('Unique ', distinctUnion(arr, arr2));

Adding library function for sorting array gives undefined

I am trying to add a Library function for sorting Items in an array. Though I got link and way, but when trying to make a library function, this doesn't work. can someone help me out as it is responding undefined as result.
var arr1 = [5, 4, 2, 6, 9, 2, 8, 1, 6];
Array.prototype.sortItems = function(){
this.sort((a,b) => a - b);
}
console.log(arr1.sortItems());
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
you need to return the result of this.sort()
var arr1 = [5, 4, 2, 6, 9, 2, 8, 1, 6];
Array.prototype.sortItems = function(){
return this.sort((a,b) => a - b);
}
console.log(arr1.sortItems());
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try returning the result
var arr1 = [5, 4, 2, 6, 9, 2, 8, 1, 6];
Array.prototype.sortItems = function(){
return this.sort((a,b) => a - b);
}
console.log(arr1.sortItems());
FYI, compareFunction is optional
var arr1 = [5, 4, 2, 6, 9, 2, 8, 1, 6];
console.log(arr1.sort());

Javascript - Put array items, including their duplicates, into a new array

I couldn't find an answer to this specific question on S.O.
Let's say I have an array of strings, or in this case, numbers:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
I'd like the output to be:
var output = [[1,1,1], [2], [3,3,3,3,3], [4], [5, 5, 5]];
I was hoping to use Lodash but most of that stuff tends to remove duplicates rather chunk them together into their own array. Maybe some kind of .map iterator?
The order of the output doesn't really matter so much. It just needs to chunk the duplicates into separate arrays that I'd like to keep.
You can use reduce to group the array elements into an object. Use Object.values to convert the object into an array.
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
var result = Object.values(x.reduce((c, v) => {
(c[v] = c[v] || []).push(v);
return c;
}, {}));
console.log(result);
Shorter version:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
var result = Object.values(x.reduce((c, v) => ((c[v] = c[v] || []).push(v), c), {}));
console.log(result);
You can do this with Array.reduce in a concise way like this:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5]
let result = x.reduce((r,c) => (r[c] = [...(r[c] || []), c],r), {})
console.log(Object.values(result))
The exact same with lodash would be:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5]
let result = _.values(_.groupBy(x))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Using _.values to extract the values of the grouping object and _.groupBy to get the actual groupings
Use Array#prototype#reduce to group them:
const x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
let helperObj = {};
const res = x.reduce((acc, curr) => {
// If key is not present then add it
if (!helperObj[curr]) {
helperObj[curr] = curr;
acc.push([curr]);
}
// Else find the index and push it
else {
let index = acc.findIndex(x => x[0] === curr);
if (index !== -1) {
acc[index].push(curr);
}
}
return acc;
}, []);
console.log(res);
Since you're hoping to use Lodash, you might be interested in groupBy. It returns on object, but the _.values will give you the nested array:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
let groups = _.values(_.groupBy(x))
console.log(groups)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Here's an imperative solution:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
x.sort();
var res = [];
for (const [i, n] of x.entries()) {
if (n !== x[i-1]) res.push([n]);
else res[res.length-1].push(n);
}
console.log(res);

Merge elements of array with comma with max counter

So I have an array of ids something like this:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
I need a function that will be called like mergeArray(arr, 3), and it should return comma separated values with maximum of 3 elements like this:
const newArr = ['1,2,3', '4,5,6', '7,8,9', '10,11'];
How can I do this? If possible with ES6 functions for simpler code.
slice your array into 3 lengths arrays and directly join them
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
const mergeArray = (arr, size) => {
let res = [];
for (i = 0; i < arr.length; i += size) {
res.push(arr.slice(i, i + size).join(','));
}
return res;
}
console.log(mergeArray(arr, 3));
You can split() the array into the specific size and join() them before pushing into the resulting array:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
var i, j, newArr=[], size = 3;
for (i=0,j=arr.length; i<j; i+=size) {
newArr.push(arr.slice(i, i+size).join());
}
console.log(newArr);
One of the ways to do it is with Array.prototype.reduce and Array.prototype.map:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
function mergeArray(arr, n) {
return arr
.reduce((all, el, i) => {
const ind = Math.floor(i/n);
all[ind] = [...all[ind] || [], el]
return all;
},[])
.map(a => a.join(','))
}
console.log(mergeArray(arr, 3));
You could join the array and match the wanted parts with a regular expression.
var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
result = data.join(',').match(/\d+(,\d+(,\d+)?)?/g)
console.log(result);

Get item what's not on the 2nd, 3rd arrays - JS

I am trying to create a function that will get the items that cannot be seen on the 2nd or 3rd and upcoming arrays passed within the function.
Right now my function gets only the similar items. How can I make it get the difference (w/c are the items that doesn't exist to the 2nd and 3rd and proceeding arrays.
const callM = function(arrays) {
arrays = Array.prototype.slice.call(arguments);
let result = [];
for(let i = 1; i < arrays.length; i++){
for(let x = 0; x < arrays[i].length; x++){
if(arrays[0].includes(arrays[i][x])){
result.push(arrays[i][x]);
}
}
}
return result;
};
console.log(callM([1, 2, 3, 4, 5], [5, 2, 10])); // -> must be [1, 3, 4]
console.log(callM([1, 2, 3, 4, 5], [5, 2, 10], [7, 1, 8])); // -> must be [3,4]
The logic right now is a bit off as it gets the opposite. How do i fix this?
Also is there a way to do this using Higher Order functions such as reduce or filter?
Thanks!
I'd think about this differently. As the difference between two sets: array 0 and array 1...n
To get array 0, just shift it off the top
const arr0 = arrays.shift()
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
This removes the first array from arrays
Next we combine the remaining arrays
const arrN = arrays.reduce(function(prev, curr) {
return prev.concat(curr)
})
Ref: http://www.jstips.co/en/javascript/flattening-multidimensional-arrays-in-javascript/
Unneeded, handled by includes as mentioned by #Phil
Next filter duplicates from arrN by comparing with itself
const unique = arrN.filter(function(elem, index, self) {
return index == self.indexOf(elem);
})
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Next filter with includes to find the difference (or union)
const diff = arr0.filter(function(item) {
return !arrN.includes(item))
}
Full snippet:
function callM(arrays) {
const arr0 = arrays.shift()
const arrN = arrays.reduce(function(prev, curr) {
return prev.concat(curr)
})
//const unique = arrN.filter(function(elem, index, self) {
// return index == self.indexOf(elem)
//})
return arr0.filter(function(item) {
return !arrN.includes(item)
})
}
console.log(callM([[1, 2, 3, 4, 5], [5, 2, 10]]))
console.log(callM([[1, 2, 3, 4, 5], [5, 2, 10], [7, 1, 8]]))
of course ES6 would be easier. ;)
const callM = (first, ...rest) => {
const arrays = [].concat(...rest)
return first.filter(item => !arrays.includes(item))
}
console.log(callM([1, 2, 3, 4, 5], [5, 2, 10]))
console.log(callM([1, 2, 3, 4, 5], [5, 2, 10], [7, 1, 8]))
A short solution for small and medium sized arrays:
// Return elements in array but not in filters:
function difference(array, ...filters) {
return array.filter(el => !filters.some(filter => filter.includes(el)));
}
// Example:
console.log(difference([1, 2, 3, 4, 5], [5, 2, 10])); // [1, 3, 4]
console.log(difference([1, 2, 3, 4, 5], [5, 1, 10], [7, 2, 8])); // [3, 4]
For large inputs, consider creating a Set from all filters and filtering in linear time using set.has(el).
In order to fix your implementation, you could label the outer for-loop and continue from there whenever a filter contains one of the array elements. Only when all filters pass without match, you push the array element into the result:
// Return elements in array but not in filters:
function difference(array, ...filters) {
const result = [];
loop: for (const el of array) {
for (const filter of filters) {
if (filter.includes(el)) continue loop;
}
result.push(el);
}
return result;
}
// Example:
console.log(difference([1, 2, 3, 4, 5], [5, 2, 10])); // [1, 3, 4]
console.log(difference([1, 2, 3, 4, 5], [5, 2, 10], [7, 1, 8])); // [3,4]
If you're willing to use Underscore, you can do this in one line of code:
console.log(_.difference([1, 2, 3, 4, 5], [5, 2, 10], [7, 1, 8]))
https://jsfiddle.net/o1zuaa6m/
You can use array#reduce to create object lookup of all the other array excluding the first array. Then use array#filter to get the values which are not present in the object lookup
var callM = (first, ...rest) => {
var combined = rest
.reduce((res,arr) => res.concat(arr))
.reduce((o, v) => {
o[v] = true;
return o;
},{});
return first
.filter(v => !combined[v]);
}
console.log(callM([1, 2, 3, 4, 5], [5, 2, 10])); // -> must be [1, 3, 4]
console.log(callM([1, 2, 3, 4, 5], [5, 2, 10], [7, 1, 8])); // -> must be [3,4]
The "proper" way to exclude values is usually to use a lookup hash set with the values to exclude:
const callM = (a, ...b) => (b = new Set(b.concat.apply(...b)), a.filter(v => !b.has(v)))
console.log(callM([1, 2, 3, 4, 5], [5, 2, 10])); // [1, 3, 4]
console.log(callM([1, 2, 3, 4, 5], [5, 2, 10], [7, 1, 8])); // [3, 4]

Categories