Given the array:
myArr = [
{'a':1},
{'b':1},
{'b':2},
{'a':1},
{'b':2}
]
And the index 0, which has the object {'a':1}, I would like to get back the array:
[{'b':1},{'b':2},{'b':2}] keeping the original sort order.
That is removing the object in index 0 and all other objects which are the equivalent.
Is there an elegant way?
If you want to remove the same object, it is simple:
a1 = { a: 1 }
b1 = { b: 1 }
b2 = { b: 2 }
myArr = [ a1, b1, b2, a1, b2 ]
var filtered = myArr.filter(o => o != a1)
console.log(filtered);
// [ {b: 1}, {b: 2}, {b: 2} ]
However, if you want to remove an equivalent object, it gets complicated, because by default JavaScript does not have an object equivalence test. You can implement one yourself, or rely on one of the libraries like lodash:
var myArr = [
{'a':1},
{'b':1},
{'b':2},
{'a':1},
{'b':2}
];
var filtered = _.filter(myArr, o => !_.isEqual(o, {a: 1}));
console.log(filtered);
// [ {b: 1}, {b: 2}, {b: 2} ]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.6/lodash.min.js"></script>
Then again, if you're using lodash, you might as well just use it to the full extent:
var myArr = [
{'a':1},
{'b':1},
{'b':2},
{'a':1},
{'b':2}
];
var filtered = _.differenceWith(myArr, [{a: 1}], _.isEqual);
console.log(filtered);
// [ {b: 1}, {b: 2}, {b: 2} ]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.6/lodash.min.js"></script>
which basically does the same thing, but a bit more readably.
This works for me
myArr = [
{'a':1},
{'b':1},
{'b':2},
{'a':1},
{'b':2}
]
//Get first item
for(var key in myArr[0]){
var firstItem = key;
}
alert('First item: ' + firstItem);
//Remove matches
var removedItems = []; //Not needed, just used to show you what it's removing.
myArr.forEach(function(item){
for (var key in item){
if(key == firstItem){
removedItems.push(key); //Not needed
myArr.splice(item, 1); //Remove the array entry
}
}
});
alert('Removed items: ' + removedItems);
try myArr.shift();
It will return {'a':1}
And myArr will be [{'b':1},{'b':2},{'b':2}]
Related
This question already has answers here:
How to remove all duplicates from an array of objects?
(77 answers)
Closed 5 years ago.
Could you let me know how do I remove duplicates from an Array in type script.
My array will look something like
a = [{a: 1, b: 2}, {a: 1, b: 2}, {c: 3, d: 4}]
I am looking to get
a = [{a: 1, b: 2}, {c: 3, d: 4}]
I used Set data strucure like below
a = Array.from(new Set(a))
but still no use. Please let me know how to remove duplicates from an array using single statement?
Is not in a single statement but is short.
var a = [{a: 1, b: 2}, {a: 1, b: 2}, {c: 3, d: 4}];
a = a.filter((value, index, array) =>
!array.filter((v, i) => JSON.stringify(value) == JSON.stringify(v) && i < index).length);
console.log(a);
Your question sees like this:
Delete duplicated elements in array of objects Javascript
But like in the comment will fails for:
var a = [{a: 1, b: 2}, {b: 2, a: 1}];
You need a custom compare for your case:
function isEqual(a, b){
for(var i in a)
if(a[i] != b[i])
return false;
for(var i in b)
if(b[i] != a[i])
return false;
return true;
}
var a = [{a: 1, b: 2}, {b: 2, a: 1}, {c: 3, d: 4}];
a = a.filter((value, index, array) =>
!array.filter((v, i) => isEqual(value, v) && i < index).length);
console.log(a);
You can compare ids or somenthing like this to identify equal object in this sample i just compare the properties.
Like #Juan Mendes said in comment:
The reason your code doesn't filter elements is because two similar objects are still considered different objects because they point to different objects. You need to write your own code that uses a custom comparator.
So theres tons of posts on sorting something like this:
var arr = [{a: 1}, {b: 2}] alphabetically by key, but what if you have something like var arr = [{a: 100}, {a: 50}], what I want is to then say "oh you're the same? lets sort you then by value (which will always be a number).
I am unsure how to do either in lodash or any other similar javascript way.
The end result should be either:
[{b: 2}, {a: 1}] // Keys are different (alphabetical)
// or:
[{a: 50}, {a: 100}] // Keys are the same (lowest to highest)
Everything I have seen on stack overflow becomes a quick mess (code wise), and I was thinking, there are sort methods on lodash, but how exactly do I achieve what I want given the circumstances ??
Any ideas?
Some one asked a good question, are there more keys? Are they only a and b?
There would only be two objects in this array at any given time and yes the keys would only ever be strings, in this case the strings could be anything, cat, dog, mouse, apple, banana ... What ever.
The values will only ever be numbers.
Clearing the air
If the keys match, only sort the array by value, if the keys do not match, only sort the array by key. There will only ever be two objects in this array. Apologies for the misunderstanding.
You can use only one function to perform the two types of sorting (works for your case, in which you have only an array with two items, but it is completely generic regarding the array length):
var arr1 = [{a: 30}, {a: 2}];
var arr2 = [{b: 30}, {a: 2}];
function sortArr(arr) {
return arr.sort((a, b) => {
var aKey = Object.keys(a)[0];
var bKey = Object.keys(b)[0];
return (aKey !== bKey) ? aKey.localeCompare(bKey) : a[aKey] - b[bKey];
});
}
var sortedArr1 = sortArr(arr1);
var sortedArr2 = sortArr(arr2);
console.log(sortedArr1);
console.log(sortedArr2);
In case you always have one property in your objects you can first sort by key using localeCompare and then by value of that property.
var arr = [{b: 2}, {b: 10}, {a: 1}, {c: 1}, {a: 20}]
arr.sort(function(a, b) {
var kA = Object.keys(a)[0]
var kB = Object.keys(b)[0]
return kA.localeCompare(kB) || a[kA] - b[kB]
})
console.log(arr)
Before sorting you can create array of unique keys that you can use to check if all object have the same key by checking if length is > 1 and use that in sort function.
var arr = [{b: 10}, {b: 2}, {a: 1}, {c: 1}, {a: 20}, {b: 22}]
var arr2 = [{a: 10}, {a: 2}, {a: 1}, {a: 22}]
function customSort(data) {
var keys = [...new Set([].concat(...data.map(e => Object.keys(e))))]
data.sort(function(a, b) {
var kA = Object.keys(a)[0]
var kB = Object.keys(b)[0]
return keys.length > 1 ? kA.localeCompare(kB) : a[kA] - b[kB]
})
return data;
}
console.log(customSort(arr))
console.log(customSort(arr2))
var arr = [{b: 2}, {a: 1}, {b: 1}, {a: 100}, {a: 20}];
arr.sort(function(a, b) {
var aKey = a.hasOwnProperty("a")? "a": "b", // get the first object key (if it has the property "a" then its key is "a", otherwise it's "b")
bKey = b.hasOwnProperty("a")? "a": "b"; // same for the second object
return aKey === bKey? // if the keys are equal
a[aKey] - b[aKey]: // then sort the two objects by the value of that key (stored in either aKey or bKey)
aKey.localeCompare(bKey); // otherwise sort by the strings aKey and bKey (the keys of the two objects)
});
console.log(arr);
So given a simple json object
[
{"a": 1},
{"b": 2},
{"c": 3},
{"d": 4}
]
and an array like this
var arr = ["A", "B", "C"];
I want to write the most efficient function to match the lower case keys with their upper case counter parts and replace them with the uppercase letters, I started by turning the array into a object so I wont have to iterate over and over again, but Im stuck. Can someone please show me how they would handle this in the most efficient way?
Without further information on your amount of keys/possible keys, trying to make a generic solution would be like this:
var arr = [
{"a": 1},
{"b": 2},
{"c": 3},
{"d": 4}
]
var match = ["A", "B", "C"];
var objMatch = {}
for(var i=0;i<match.length;i++) objMatch[match[i].toLowerCase()] = match[i] // pass it to an object for efficient matching
for(var i=0;i<arr.length;i++){
for(var key in arr[i]){ // check if we need to replace the key
if(objMatch.hasOwnProperty(key)){
var temp = arr[i][key] // keep old value
delete arr[i][key] // delete key
arr[i][objMatch[key]] = temp // set new key with same old value
}
}
}
console.log(arr)
From what i understand from your question
var arrayOne = [
{"a": 1},
{"b": 2},
{"c": 3},
{"d": 4}
];
var arrayTwo = ["A", "B", "C"];
var tempArray = {};
$.each(arrayOne, function(key,value){
for(arrayOneKey in value){
$.each(arrayTwo, function(index,vl) {
if(vl.toLowerCase() == arrayOneKey.toLowerCase()){
tempArray[vl]=key+1;
}
});
}
});
console.log(tempArray);
var a=[
{"a": 1},
{"b": 2},
{"c": 3},
{"d": 4}
];
var arr = ["A", "B", "C"];
Define a method in Object's prototype chain to rename Object keys:
Object.prototype.changeKey = function (oName, nName) {
if (oName == nName) {
return this;
}
if (this.hasOwnProperty(oName)) {
this[nName] = this[oName];
delete this[oName];
}
return this;
};
Then find the key which matches the elements of array, then change it:
for(var i=0;i<arr.length;i++){
for(key in a[i]){
if(key === arr[i].toLowerCase()){a[i].changeKey (key,arr[i])}
}
}
Here is a fiddle
Don't make things complicated. Use map and return a new array:
function transform(arr, keys) {
return arr.map(function(el) {
var obj = {};
var key = Object.keys(el)[0];
var uc = key.toUpperCase();
obj[keys.indexOf(uc) > -1 ? uc : key] = el[key];
return obj;
});
}
transform(input, arr);
DEMO
You could use an helper object and loop throu all items and all keys.
var arr0 = [{ "a": 1 }, { "b": 2 }, { "c": 3 }, { "d": 4 }],
arr1 = ["A", "B", "C"],
obj = Object.create(null);
arr1.forEach(function (a) {
obj[a.toUpperCase()] = a;
});
arr0.forEach(function (a) {
Object.keys(a).forEach(function (k) {
var v = a[k];
if (k.toUpperCase() in obj) {
delete a[k];
a[obj[k.toUpperCase()]] = v;
}
});
});
document.write('<pre>' + JSON.stringify(arr0, 0, 4) + '</pre>');
I have two objects:
a = {A: 1, B: 2};
a = {C: 3, D: 4};
I need to put the property values of the objects in to one array. So, i'm doing this by iterate each of the objects, but what next, pushing it into one array returns two separated...
$.each(a, function(_key, _val) {
var arr = [];
arr.push(_val);
console.log(arr);
});
How to do this? Is it possible?
I need this: arr = [1, 2, 3, 4];
You are initializing the arr inside the each everytime. Try this:
var arr = [];
$.each(a, function(_key, _val) {
arr.push(_val);
console.log(arr);
});
Here is a fiddle:
https://jsfiddle.net/aarLgmtL/
var a = {A: 1, B: 2};
var b = {C: 3, D: 4};
function join(source, target) {
$.each(source, function(_key, _val) {
target.push(_val);
});
}
var arr = [];
join(a, arr);
join(b, arr);
$("#result").html(JSON.stringify(arr));
You could try using .concat as well. Here is an example from w3schools:
var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var children = hege.concat(stale);
http://www.w3schools.com/jsref/jsref_concat_array.asp
Is this what you are looking for?
Don't initialize array in $.each function. It will assign new array every time $.each function call so it end up with last array element in arr variable.
a = {
A: 1,
B: 2
};
b = {
C: 3,
D: 4
};
var arr = [];
function pushToArray(a) {
$.each(a, function(_key, _val) {
arr.push(_val);
});
}
pushToArray(a);
pushToArray(b);
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Make sure that you don't define different object with same name else end up with last object assigned to that variable.
You can simply achieve this by using Object.assign
var a = {A: 1, B: 2};
var b = {C: 3, D: 4};
var copy = Object.assign(a, b);
var result =[];
for(var i in copy){
result.push(copy[i]);
}
console.log(result);
Thanks.
The approach outlined below first creates two separate arrays, one from a and one from b, and then concatenates them together (with a little help from the jQuery Array#map method.)
a = {A: 1, B: 2};
b = {C: 3, D: 4};
var arrayFromA = $.map(a, function(value, index) {
return [value];
});
var arrayFromB = $.map(b, function(value, index) {
return [value];
});
finalArray = arrayFromB.concat(arrayFromA);
In javascript, is there an easy way to sort key-value pairs by the value (assume the value is numeric), and return the key? A jQuery way to do this would be useful as well.
(There are a lot of related questions about key-value pairs here, but I can't find one specifically about sorting.)
There's nothing easy to do this cross-browser. Assuming an array such as
var a = [
{key: "foo", value: 10},
{key: "bar", value: 1},
{key: "baz", value: 5}
];
... you can get an array of the key properties sorted by value as follows:
var sorted = a.slice(0).sort(function(a, b) {
return a.value - b.value;
});
var keys = [];
for (var i = 0, len = sorted.length; i < len; ++i) {
keys[i] = sorted[i].key;
}
// keys is ["bar", "baz", "foo"];
Let's assume we have an Array of Objects, like:
var data = [
{foo: 6},
{foo: 2},
{foo: 13},
{foo: 8}
];
We can call Array.prototype.sort()help, use Array.prototype.map()help to map a new array and Object.keys()help to grab the key:
var keys = data.sort(function(a,b) {
return a.foo - b.foo;
}).map(function(elem, index, arr) {
return Object.keys(elem)[0];
});
Be aware of, Array.prototype.map() requires Javascript 1.6 and Object.keys() is ECMAscript5 (requires Javascript 1.8.5).
You'll find alternative code for all those methods on MDC.
As far as I know, there isn't a built-in Javascript function to sort an array by its keys.
However, it shouldn't take too much code to do it: just extract the keys into their own array, sort them using the normal sort function, and rebuild the array in the right order. Something like this should do the trick:
function SortArrayByKeys(inputarray) {
var arraykeys=[];
for(var k in inputarray) {arraykeys.push(k);}
arraykeys.sort();
var outputarray=[];
for(var i=0; i<arraykeys.length; i++) {
outputarray[arraykeys[i]]=inputarray[arraykeys[i]];
}
return outputarray;
}
Now you can just call your function like so:
var myarray = {'eee':12, 'blah':34 'what'=>66, 'spoon':11, 'snarglies':22};
myarray = SortArrayByKeys(myarray);
And the output will be:
{'blah':34, 'eee':12, 'spoon':11, 'snarglies':22, 'what':66}
Hope that helps.
Working test page here: http://jsfiddle.net/6Ev3S/
Given
var object = {
'a': 5,
'b': 11,
'c': 1,
'd': 2,
'e': 6
}
You can sort object's keys by their values using the following:
Object.keys(object).sort(function (a, b) {
return object[a] - object[b]
}))
Result
[ 'c', 'd', 'a', 'e', 'b' ]
If you can't count on the exended array and object properties,
you can use the original Array methods-
function keysbyValue(O){
var A= [];
for(var p in O){
if(O.hasOwnProperty(p)) A.push([p, O[p]]);
}
A.sort(function(a, b){
var a1= a[1], b1= b[1];
return a1-b1;
});
for(var i= 0, L= A.length; i<L; i++){
A[i]= A[i][0];
}
return A;
}
//test
var Obj={a: 20, b: 2, c: 100, d: 10, e: -10};
keysbyValue(Obj)
/* returned value: (Array)
e,b,d,a,c
*/