Related
I want to merge two arrays which have some duplicated values into one array which has no duplicates. I am using concat but the result is all value.
var a = [1,2,2];
var b = [1,2,3,3];
var c = a.concat(b);
console.log(c);
Expected output:
[1, 2, 3]
Merge them into a Set, and turn that set back into an array:
var a = [1,2,2];
var b = [1,2,3,3];
var c = [...new Set([...a, ...b])];
console.log(c);
You can also use concat and Array.from as an alternative to spread syntax if necessary:
var a = [1,2,2];
var b = [1,2,3,3];
var c = Array.from(new Set(a.concat(b)));
console.log(c);
Add both of them to a Set, which is a data structure that ignores duplicates.
var x = [{a:1, b:4,c:5}, {a:1, b:2,c:7}];
var y = [{a:1, b:2,c:6}, {a:1, b:2,c:8}];
I want to compare based on first 2 key i.e a,b and get the index if it is unequal. In above example output should be fetched as 0 since b value is nt equal. How do we achieve in javascript or Lodash ? Thank you.
So you want a compare function which will compare an array of object in which you want index of an object whose two properties a and b are not equal.
Below implementation return such index(0-base) if exit else return -1.
function compare(x,y){
for(let i=0;i<x.length && i<y.length;i++){
if(x[i].a!=y[i].a || x[i].b!=y[i].b)
return i;
}
return -1;
}
var x = [{a:1, b:4,c:5}, {a:1, b:2,c:7}];
var y = [{a:1, b:2,c:6}, {a:1, b:2,c:8}];
console.log(compare(x,y)); //0
y = [{a:1, b:4,c:6}, {a:1, b:2,c:8}];
console.log(compare(x,y));//-1
y = [{a:1, b:4,c:6}, {a:1, b:3,c:8}];
console.log(compare(x,y));//1
Hope this you want.
Assuming you want to compare two objects in an array by first two keys, here's a working example. Please, feel free to elaborate.
var x = [{a:1, b:4,c:5},{a:1, b:2,c:7}];
var y = [{a:1, b:2,c:6}, {a:1, b:2,c:8}];
function customizer(obj1, obj2) {
const [a, b] = Object.keys(obj1).slice(0, 2);
return obj1[a] === obj2[a] && obj1[b] === obj2[b];
}
xIsEqual = _.isEqualWith(x[0], x[1], customizer);
yIsEqual = _.isEqualWith(y[0], y[1], customizer);
console.log(xIsEqual); // false
console.log(yIsEqual); // true
If you want to filter an array on a specific condition, you can use filter() :
y.filter(d => d.a !== d.b);
With Lodash:
_.filter(y, d => d.a !== d.b);
You can't rely on an order of object keys, 'cause iteration over object keys is implementation-dependent. It could differ from browser to browser.
Read this note.
For example, run the following code:
const obj1 = { a: 'a', 100: 'b', 2: 'c' };
console.log('object literal', Object.keys(obj1));
// at least in chrome it would be ["2", "100", "a"]
const obj2 = {};
obj2['a'] = 'a';
obj2['100'] = 'b';
obj2['2'] = 'b';
console.log('object with keys added in a specific order', Object.keys(obj2));
// same ["2", "100", "a"]
Case: We have 'n' number of arrays stored in an array (Array of Arrays). Now that each child array in this parent array can have elements that may or may not be present in other child arrays. Output - I need to create an array which has the all the elements present in all the child arrays excluding the duplicates.
I do not want to concatenate all the arrays into a single array and use unique method to filter out. I need to create unique array then and there during iteration.
Ex:
var a[] = [1,2,3,4,5];
var b[] = [1,2,7,8];
var c[] = [1,2,3,4,5,6,7,8];
var d[] = [9,10,11,12];
var arr[] = [a,b,c,d]
Output must be [1,2,3,4,5,6,7,8,9,10,11,12]
P.S: I can concat the arrays and use jquery unique function to resolve this, but i need a solution in javascript alone. Thanks
You can use array#reduce to flatten your array and then use Set to get distinct values and use array#from to get back array from Set.
var a = [1,2,3,4,5];
var b = [1,2,7,8];
var c = [1,2,3,4,5,6,7,8];
var d = [9,10,11,12];
var arr = [a,b,c,d]
var result = Array.from(new Set(arr.reduce((r,a) => r.concat(a))));
console.log(result);
Try using .filter when adding each array to the final one, filtering out the duplicates:
a.filter(function(item) {
return !finalArray.contains(item));
});
Answer using Sets:
var a = [1,2,3,4,5];
var b = [1,2,7,8];
var c = [1,2,3,4,5,6,7,8];
var d = [9,10,11,12];
var concat = a.concat(b).concat(c).concat(d);
var union = new Set(concat);
//console.log(union);
ES6 Answer:
let a = new Set([1,2,3,4,5]);
let b = new Set([1,2,7,8]);
let c = new Set([1,2,3,4,5,6,7,8]);
let d = new Set([9,10,11,12]);
let arr = new Set([...a,...b,...c,...d]);
//Result in arr.
Whats going on???
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set:
The Set object lets you store unique values of any type, whether
primitive values or object references.
So when we initialise Sets passing arrays to the constructor we basically ensure that there are no duplicate values.
Then in the last line, we concat all the Sets we initialised prior into a final set.
The ... notation converts the Set into an array, and when we pass the 4 arrays to the constructor of the Set they get concatenated and a Set of their unique values is created.
Here is a functional alternative written in ES5.
var flatten = function(list) {
return list.reduce(function(acc, next) {
return acc.concat(Array.isArray(next) ? flatten(next) : next);
}, []);
};
var unique = function(list) {
return list.filter(function(element, index) {
return list.indexOf(element) === index;
})
}
var a = [1,2,3,4,5];
var b = [1,2,7,8];
var c = [1,2,3,4,5,6,7,8];
var d = [9,10,11,12];
var arr = [a,b,c,d];
var result = unique(flatten(arr));
console.log(result);
If you support ES6, arrow function can make that code even shorter.
Here is a solution that uses a plain object for resolving duplicates, and only uses basic ES3 JavaScript. Runs in IE 5.5 and higher, and with O(n) time complexity.
function uniques(arr) {
var obj = {}, result = [];
for (var i = 0; i < arr.length; i++) {
obj[arr[i]] = true;
}
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) result.push(+prop);
}
return result;
}
// Example use
var a = [1,2,3,4,5],
b = [1,2,7,8],
c = [1,2,3,4,5,6,7,8],
d = [9,10,11,12];
var result = uniques(a.concat(b, c, d));
console.log('Result: ' + result);
As an object can only have a unique set of properties (no duplicates), the use of all array values as properties in an object will give you an object with a property for each unique value. This happens in the first loop. NB: the value given to those properties is not relevant; I have used true.
Then the result is just the conversion of those properties back to array values. This happens in the second loop.
var a = [1,2,3,4,5];
var b = [1,2,7,8];
var c = [1,2,3,4,5,6,7,8];
var d = [9,10,11,12];
var result = a.concat(b,c,d);
function remvDup(result){
var tmp = [];
for(var i = 0; i < result.length; i++){
if(tmp.indexOf(result[i]) == -1){
tmp.push(result[i]);
}
}
return tmp;
}
console.log(remvDup(result));
Becuase the OP mentioned that he cannot use 'Set' as it is not supported on the targeted browsers, I would recommand using the 'union' function from the lodash library.
See union's documentation here
I have below array ,
["aa","bb"]
I have below object,
{"aa":1,"bb":2,"cc":3}
and I need result below,
{"cc":3}
I need to compare array with object keys, using looping it is possible,but it take more time for large amount data, is there any other fastest way to get my result without using loop, Anyhelp Appreciated...
To avoid quadratic time complexity you could use a Set and pass that as the this argument to the filter. Then recompose an object from those filtered keys with Object.assign:
var a = ["aa","bb"];
var b = {"aa":1,"bb":2,"cc":3};
var difference = Object.assign(...Object.keys(b).filter(function(e){
return !this.has(e);
}, new Set(a)).map(key => ({ [key]: b[key] }) ));
console.log(difference);
If you are OK with mutating the object, then you can use delete to remove the unwanted properties.
const props = ["aa","bb"];
const obj = {"aa": 1,"bb": 2,"cc": 3};
props.forEach(prop => delete obj[prop]);
console.log(obj);
Or just loop over the array of property names with for...of.
const props = ["aa","bb"];
const obj = {"aa": 1,"bb": 2,"cc": 3};
for (prop of props) delete obj[prop];
console.log(obj);
If you don't want to mutate the object, but instead create a new one without he unwanted properties, then you can do a shallow clone first with
newObj = {...obj};
Loop through the object and check to see if the property doesn't exist in the array:
var a = ["aa","bb"];
var o = {"aa":1,"bb":2,"cc":3};
// Loop through object
for(var prop in o){
// If property doesn't exist in array...
if(a.indexOf(prop) === -1){
console.log(prop + ":" + o[prop]);
}
}
Something like this maybe?
var a = ["aa","bb"];
var b = {"aa":1,"bb":2,"cc":3};
var result = {};
Object.keys(b).filter(function(e){
return a.indexOf(e) < 0;
}).forEach(function(e){
result[e] = b[e];
});
console.log(result);
you can loop through the object and compare the object keys with the array items and return the missing keys as an object.
var a = ["aa","bb"] ;
var o = {"aa":1,"bb":2,"cc":3,'dd':4};
function get(o){
var p = {};
for(var key in o){
if(a.indexOf(key) == -1){
p[key] = o[key];
}
}
return p;
}
var c = get(o);
console.log(c);
You can use Object.assign(), Object.entries(), Array.prototype.includes() to determine if current key in object is an element of array, return object using computed property or false, which does not result in property being assigned to new object
var arr = ["aa","bb"]
var obj = {"aa":1,"bb":2,"cc":3}
var res = Object.assign({}
, ...Object.entries(obj).map(([key, prop]) =>
!arr.includes(key) && {[key]:prop})
);
console.log(res);
I have this:
var a = {};
a[1] = 1;
a[4] = 4;
console.log(JSON.stringify(a));
then I get:
{"1":1,"4":4}
but I want to get:
{1:1,4:4}
how to reach this? In other words, I want to keys be real int.
When you call JSON.stringify() method it creates a valid JSON string.
One of the rules for valid JSON is that every property should be in "quotes".
So thats why it is impossible to get such result as you want using JSON.stringify.
If you want to just convert such object to array it is possible, for example usin such function.
function numerableObjectToArr(obj) {
var result = [];
var keys = Object.keys(obj);
keys.forEach(function(item){
result.push(obj[item]);
})
return result;
}
var a = {};
a[1] = 1;
a[4] = 4;
numerableObjectToArr(a); // returns [1, 4]
But in this way you will just receive Array with values of existing properties in the obj.
But if your prop name means the index in the array, and you are sure that there will be always number as a prop name - you can improve this function:
function numerableObjectToArr(obj) {
var result = [];
var keys = Object.keys(obj);
keys.forEach(function(item){
result[+item] = obj[item]; //we put index, then we put value to that place in array
})
return result;
}
var a = {};
a[1] = 1;
a[4] = 4;
numerableObjectToArr(a); // returns [undefined, 1, undefined, undefined, 4]
I'm not sure you can do what you're trying to do the as the keys have to be string values. I'd advise having string name for your keys (i.e 1 = One, 2 = Two, etc). You could then try this:
var a = {};
a.one = 1;
a.two = 2;
a.three = 3;
a.four = 4;
console.log(JSON.stringify(a));
I hope this helps.
var a = {};
a[1] = 1;
a[4] = 4;
alert(JSON.stringify(a).replace(/\"([0-9]+)\":/g, '$1:'));
But it is kludge. JSON - has a string keys.