I have an array like this
let data = [{x:1,y:2,z:3},{x:1,y:2,z:3},{x:1,y:2,z:4},{x:11,y:2,z:3}]
Now I want to get only those items whose x,y,z values are the same.so expected output should be
{x:1,y:2,z:3}
Because {x:1,y:2,z:3} has duplicate values but rest of them not so I don't want to get rest of them because they do not have any duplicates. Please tell me how can I achieve this?
For lodash 4.17.15,
You can first use _.uniqWith and _.isEqual to find the unique values.
_.uniqWith(data, _.isEqual); // [{x:1,y:2,z:3},{x:1,y:2,z:4},{x:11,y:2,z:3}]
Then use _.difference to remove the unique values from the array, leaving just the duplicates
_.difference(data, _.uniqWith(data, _.isEqual)); // [{x:1,y:2,z:3}]
let data = [{x:1,y:2,z:3},{x:1,y:2,z:3},{x:1,y:2,z:4},{x:11,y:2,z:3},{x:11,y:2,z:3}]
function filterDuplicates(data) {
let dic = {};
data.forEach(obj => {
let strObj = JSON.stringify(obj, Object.keys(obj).sort());
if(strObj in dic) {
++dic[strObj];
return;
}
dic[strObj] = 0;
})
return Object.entries(dic).filter(([key, value]) => value > 0).map(([el]) => JSON.parse(el));
}
console.log(filterDuplicates(data));
Build an object to track the duplicates and use Object.values and filter
let data = [
{ x: 1, y: 2, z: 3 },
{ x: 1, y: 2, z: 3 },
{ x: 1, y: 2, z: 4 },
{ x: 11, y: 2, z: 3 },
];
const all = {};
data.forEach(({ x, y, z }) => {
const key = `x${x}y${y}z${z}`;
all[key] = key in all ? { x, y, z } : null;
});
const res = Object.values(all).filter(Boolean);
console.log(res);
Related
I have this array above and I need every property of it
let arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}]
How could I extract every single key/value of it, once in theory, I don't know any of them?
I have already tried using object.keys but it returns the indexes of my array.
This should work
const arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}];
// to iterate over each element in the arry
arr.forEach(a => {
// To Iterate over each key in the element object
Object.keys(a).forEach(k => {
// to print the value of the 'k' key
console.log(k + ' : ' + a[k]);
})
})
1) You can use flatMap and Object.keys to get keys from an array of objects.
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const result = arr.flatMap((o) => Object.keys(o));
console.log(result);
2) To find all values in an array
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const values = arr.flatMap((o) => Object.values(o));
console.log(values);
3) If you want to find out all keys and values in an object
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const result = {
keys: [],
values: [],
};
for (let obj of arr) {
Object.entries(obj).map(([k, v]) => {
result.keys.push(k);
result.values.push(v);
});
}
console.log(result);
If you want to collect all the keys and values of a nested array of objects, you can use Array.prototype.reduce and then collect the keys and values of the nested objects in separate nested arrays, using Object.keys() and Object.values() respectively:
const arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}];
const allKeysAndValues = arr.reduce((acc, cur) => {
acc.keys.push(...Object.keys(cur));
acc.values.push(...Object.values(cur));
return acc;
}, { keys: [], values: [] });
console.log(allKeysAndValues);
A one liner could be
let arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}]
console.log( arr.map( obj => Object.entries(obj)));
I have a JavaScript object like the following below availability and reserved, here I need to subtract quantity value from availability.
var availability = {"bike":10,"cycle":3,"car":1};
var reserved ={"cycle":1,"bike":10}
how should I get this response as below?
response = {"bike":0,"cycle":2,"car":1};
Why not a simple for loop.
var availability = { bike: 10, cycle: 3, car: 1 };
var reserved = { cycle: 1, bike: 10 };
let response = {};
for (let key in availability) {
if (reserved[key]) {
response[key] = availability[key] - reserved[key];
} else {
response[key] = availability[key];
}
}
console.log(response);
Output:
{ bike: 0, cycle: 2, car: 1 }
There are many way to solve this, but I recommend using reduce().
var availibilty = {
"bike": 10,
"cycle": 3,
"car": 1
};
var reserved = {
"cycle": 1,
"bike": 10
}
function calc(a, b) {
const answer = Object.keys(a).reduce((acc, key) => {
return {
...acc,
[key]: a[key] - (b[key] || 0)
}
}, {});
console.log(answer);
}
calc(availibilty, reserved);
You can iterate through each key-value pair and subtract quantity in availability with the corresponding key in reserved. Then create your result object using Object.fromEntries().
const availability = { "bike" : 10, "cycle" : 3, "car" : 1 },
reserved ={ "cycle": 1,"bike": 10 },
result = Object.fromEntries(Object.entries(availability).map(([key, value]) => [key, value - (reserved[key] ?? 0)]));
console.log(result);
You can loop through the Object. keys() of one object you provided and subtract the other using reduce() method.
var availibilty = {"bike":10,"cycle":3,"car":1};
var reserved ={"cycle":1,"bike":10}
let response = Object.keys(availibilty).reduce((x, y) => {
x[k] = availibilty[y] - reserved[y];
return x;
}, {});
console.log(response);
Please find Array.reduce implementation.
Logic
Loop through keys of availability object.
Find the values of each keys from reserved object.
Store the difference as the value for same key in the accumulator array.
var availability = { "bike": 10, "cycle": 3, "car": 1 };
var reserved = { "cycle": 1, "bike": 10 };
const response = Object.keys(availability).reduce((acc, curr) => {
acc[curr] = availability[curr] - (reserved[curr] || 0);
return acc;
}, {});
console.log(response);
Array of dictionaries should be converted simpler form.
data = [{A:1},{B:2},{C:3}]
data = {A: 1, B: 2}
data = ["0":{ A : 1, B : 2 , C : 3}]
Both are completely different datasets. I'm trying to map it also like below format.
The above should become like
data = [
{
name: "A",
y: 1
},
{
name: "B",
y: 2
},
{
name: "C",
y: 3
}
];
I tried this following approach but it's wrong
name = {}
data.forEach(function(k,x){
return name['name'] = k , name["y"] = x
})
Please suggest me a better approach.
map each object's entries to extract the key and the value, and return an object with name and y keys:
const data = [{A:1},{B:2},{C:3}]
const output = data.map(item => {
const [name, y] = Object.entries(item)[0];
return { name, y };
});
console.log(output);
If the keys (A, B, etc) are guaranteed to be unique throughout the array, then everything becomes simpler.
const data = [{A:1},{B:2},{C:3}];
const merged = Object.assign({}, ...data);
const newData = Object.entries(merged)
.map(([name, y]) => ({ name, y }));
console.log(newData);
However, if the keys aren't guaranteed unique, then refer to CertainPerformance's answer.
you can implement like this
var data = [{A:1},{B:2},{C:3}];
var reformattedArra = data.map(obj => {
let val = {};
val.name = Object.keys(obj)[0];
val.y = obj[Object.keys(obj)[0]];
return val;
})
console.log(JSON.stringify(reformattedArra));
I would say, use Object.keys() which is widly supported
let data = [{A:1},{B:2},{C:3}];
data = Object.assign({}, ...data);
data = Object.keys(data).map(key => ({ name: key, y: data[key] }));
console.log(data);
You yould could chekc the data format and if it is not an array, build one and reduce the array by taking the objetcs and create for each key/value a new object for the result set.
function simple(data) {
return (Array.isArray(data) ? data : [data]).reduce((r, o) => [...r, ...Object.entries(o).map(([name, y]) => ({ name, y }))], []);
}
console.log(simple([{ A: 1 }, { B: 2 }, { C: 3, D: 4 }]));
console.log(simple({ A: 1, B: 2 }));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Hello this is my sample json:
{
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
}
Now I want something like
[
{"Month":"2016-01-01T00:00:00Z", "Number": 1},
{"Month":"2016-02-01T00:00:00Z", "Number": 2},
{"Month":"2016-03-01T00:00:00Z", "Number": 3}
]
How can I do this using JS/Jquery? I wanted to change it to the above mentioned format because I need to put them in html table and I found out that using the second format makes my job easier.
you can do this in the following way
let obj = {
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
};
let result = [];
for(element in obj){
result.push({"Month":element, "Number": obj[element]})
}
console.log(result);
You can use the jQuery map function to change the format of an array.
let jsonArray = {
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
};
var result = $.map(jsonArray, function (item, key) {
return {
Month: key,
Number: item
};
});
You could take the keys with Object.keys and use Array#map for mapping the new objects.
var object = { "2016-01-01T00:00:00Z": 1, "2016-02-01T00:00:00Z": 2, "2016-03-01T00:00:00Z": 3 },
result = Object.keys(object).map(function (k) {
return { Month: k, Number: object[k] };
});
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
var object1 = {
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
};
var finalArray = [];
for (var key in object1) {
if (p.hasOwnProperty(key)) { // p.hasOwnProperty this will check for duplicate key
finalArray.push({
“Month” : key,
“Number”:p[key]
});
}
}
console.log(finalArray)
Another option could include using Object.keys along with map as such...
let obj = {
'2016-01-01T00:00:00Z': 1,
'2016-02-01T00:00:00Z': 2,
'2016-03-01T00:00:00Z': 3
}
let arr = Object.keys(obj).map(key => {
return {'Month': key, 'Number': obj[key]}
});
JSFiddle demo
use $.each for travelling
a = {
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
}
var b = [];
$.each( a, function( key, value ) {
b.push({mounth: key ,number: value });
});
Output will be:
0:{mounth: "2016-01-01T00:00:00Z", number: 1}
1:{mounth: "2016-02-01T00:00:00Z", number: 2}
2:{mounth: "2016-03-01T00:00:00Z", number: 3}
I have an array of objects
list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}]
And I'm looking for an efficient way (if possible O(log(n))) to remove duplicates and to end up with
list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}]
I've tried _.uniq or even _.contains but couldn't find a satisfying solution.
Thanks!
Edit : The question has been identified as a duplicate of another one. I saw this question before posting but it didn't answer my question since it's an array of object (and not a 2-dim array, thanks Aaron), or at least the solutions on the other question weren't working in my case.
Plain javascript (ES2015), using Set
const list = [{ x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 1, y: 2 }];
const uniq = new Set(list.map(e => JSON.stringify(e)));
const res = Array.from(uniq).map(e => JSON.parse(e));
document.write(JSON.stringify(res));
Try using the following:
list = list.filter((elem, index, self) => self.findIndex(
(t) => {return (t.x === elem.x && t.y === elem.y)}) === index)
Vanilla JS version:
const list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}];
function dedupe(arr) {
return arr.reduce(function(p, c) {
// create an identifying id from the object values
var id = [c.x, c.y].join('|');
// if the id is not found in the temp array
// add the object to the output array
// and add the key to the temp array
if (p.temp.indexOf(id) === -1) {
p.out.push(c);
p.temp.push(id);
}
return p;
// return the deduped array
}, {
temp: [],
out: []
}).out;
}
console.log(dedupe(list));
I would use a combination of Arrayr.prototype.reduce and Arrayr.prototype.some methods with spread operator.
1. Explicit solution. Based on complete knowledge of the array object contains.
list = list.reduce((r, i) =>
!r.some(j => i.x === j.x && i.y === j.y) ? [...r, i] : r
, [])
Here we have strict limitation on compared objects structure: {x: N, y: M}. And [{x:1, y:2}, {x:1, y:2, z:3}] will be filtered to [{x:1, y:2}].
2. Generic solution, JSON.stringify(). The compared objects could have any number of any properties.
list = list.reduce((r, i) =>
!r.some(j => JSON.stringify(i) === JSON.stringify(j)) ? [...r, i] : r
, [])
This approach has a limitation on properties order, so [{x:1, y:2}, {y:2, x:1}] won't be filtered.
3. Generic solution, Object.keys(). The order doesn't matter.
list = list.reduce((r, i) =>
!r.some(j => !Object.keys(i).some(k => i[k] !== j[k])) ? [...r, i] : r
, [])
This approach has another limitation: compared objects must have the same list of keys.
So [{x:1, y:2}, {x:1}] would be filtered despite the obvious difference.
4. Generic solution, Object.keys() + .length.
list = list.reduce((r, i) =>
!r.some(j => Object.keys(i).length === Object.keys(j).length
&& !Object.keys(i).some(k => i[k] !== j[k])) ? [...r, i] : r
, [])
With the last approach objects are being compared by the number of keys, by keys itself and by key values.
I created a Plunker to play with it.
One liners for ES6+
If you want to find uniq by x and y:
arr.filter((v,i,a)=>a.findIndex(t=>(t.x === v.x && t.y===v.y))===i)
If you want to find uniques by all properties:
arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)
The following will work:
var a = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}];
var b = _.uniq(a, function(v) {
return v.x && v.y;
})
console.log(b); // [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 } ]
Filter the array after checking if already in a temorary object in O(n).
var list = [{ x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 1, y: 2 }],
filtered = function (array) {
var o = {};
return array.filter(function (a) {
var k = a.x + '|' + a.y;
if (!o[k]) {
o[k] = true;
return true;
}
});
}(list);
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');
No libraries, and works with any depth
Limitation:
You must provide only string or Number properties as hash objects otherwise you'll get inconsistent results
/**
* Implementation, you can convert this function to the prototype pattern to allow
* usage like `myArray.unique(...)`
*/
function unique(array, f) {
return Object.values(
array.reduce((acc, item) => ({ ...acc, [f(item).join(``)]: item }), {})
);
}
const list = [{ x: 1, y: 2}, {x: 3, y: 4}, { x: 5, y: 6}, { x: 1, y: 2}];
// Usage
const result = unique(list, item => [item.x, item.y]);
// Output: [{ x: 1, y: 2}, {x: 3, y: 4}, { x: 5, y: 6}]
console.log(result);
Snippet Sample
// Implementation
function unique(array, f) {
return Object.values(
array.reduce((acc, item) => ({ ...acc, [f(item).join(``)]: item }), {})
);
}
// Your object list
const list = [{ x: 1, y: 2}, {x: 3, y: 4}, { x: 5, y: 6}, { x: 1, y: 2}];
// Usage
const result = unique(list, item => [item.x, item.y]);
// Add result to DOM
document.querySelector(`p`).textContent = JSON.stringify(result, null, 2);
<p></p>
With Underscore's _.uniq and the standard JSON.stringify it is a oneliner:
var list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}];
var deduped = _.uniq(list, JSON.stringify);
console.log(deduped);
<script src="https://underscorejs.org/underscore-umd-min.js"></script>
However, this presumes that the keys are always specified in the same order. By sophisticating the iteratee, we can make the solution work even if the order of the keys varies. This problem as well as the solution also apply to other answers that involve JSON.stringify.
var list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {y:2, x:1}];
// Ensure that objects are always stringified
// with the keys in alphabetical order.
function replacer(key, value) {
if (!_.isObject(value)) return value;
var sortedKeys = _.keys(value).sort();
return _.pick(value, sortedKeys);
}
// Create a modified JSON.stringify that always
// uses the above replacer.
var stringify = _.partial(JSON.stringify, _, replacer, null);
var deduped = _.uniq(list, stringify);
console.log(deduped);
<script src="https://underscorejs.org/underscore-umd-min.js"></script>
For Lodash 4, use _.uniqBy instead of _.uniq.
Using lodash you can use this one-liner:
_.uniqBy(list, e => { return e.x && e.y })