I have few arrays of JSON objects.I need to iterate over the arrays and return true if there are two or more elements with the same userId value.
[{
"name":"John",
"age":30,
"userId": 5,
}],
[{
"name":"Benjamin",
"age":17,
"userId": 5,
}],
[{
"name":"Johnatan",
"age":35,
"userId": 10,
}]
Here is my method so far, I'm iterating over the array and checking is there a user with 506 userId presence.
isPostedMultiple = (data) => {
for (let j = 0; j < data.length; j++) {
if (data[j].UserId == '506') {
console.log('506 data :', data[j]);
} else {
console.log('not 506 data');
}
}
}
First of all the Object you have given is erroneous. Make it correct. Coming to the problem,
You can use a combination of Array.prototype.some and Array.prototype.filter.
data.some(
(el, i, arr) => arr.filter(_el => _el.userId == el.userId).length > 1
);
To check if there exists more than one element matching certain condition.
var data = [{
"name": "John",
"age": 30,
"userId": 5,
},
{
"name": "Benjamin",
"age": 17,
"userId": 5,
},
{
"name": "Johnatan",
"age": 35,
"userId": 10,
}
];
var result = data.some(
(el, i, arr) => arr.filter(_el => _el.userId == el.userId).length > 1
);
console.log(result)
You can merge arrays using array spread syntax and than use the reduce with the filter method
const mergedArrays = [...arr1, ...arr2, ...arr3];
const isDublicated = mergedArrays.reduce(
(acc, item) => acc || mergedArrays.filter(user => user.userId === item.userId) > 1,
false
);
To achieve expected result, use below option of using filter and findIndex to iterate over every array and compare userId
var x = [[{
"name":"John",
"age":30,
"userId": 5,
}],
[{
"name":"Benjamin",
"age":17,
"userId": 5,
}],
[{
"name":"Johnatan",
"age":35,
"userId": 10,
}]]
x = x.filter((v, i, self) =>
i === self.findIndex((y) => (
y[0].userId === v[0].userId
))
)
console.log(x);
code sample - https://codepen.io/nagasai/pen/wmWqdY?editors=1011
var jsonObj1 = [{
"name":"John",
"age":30,
"userId": 5
},
{
"name":"Benjamin",
"age":17,
"userId": 5
},
{
"name":"Johnatan",
"age":35,
"userId": 10
}];
var jsonObj2 = [{
"name":"John",
"age":30,
"userId": 5
},
{
"name":"Benjamin",
"age":17,
"userId": 15
},
{
"name":"Johnatan",
"age":35,
"userId": 10
}];
var logger = document.getElementById('logger');
logger.innerHTML = "";
function checkForDupIds(jsonObj, headerStr) {
var logger = document.getElementById('logger');
var hasDups = [];
var items = [];
for(var a=0;a<jsonObj.length;a++) {
if (items.includes(jsonObj[a].userId)) {
hasDups.push(jsonObj[a].userId);
} else {
items.push(jsonObj[a].userId);
}
}
logger.innerHTML += "<h1>" + headerStr + "</h1>";
for(var b=0;b<hasDups.length;b++) {
logger.innerHTML += "<div>" + hasDups[b] + "</div>\n";
console.log(hasDups[b]);
}
if (hasDups.length === 0) {
logger.innerHTML += "<div>No Duplicates Found</div>\n";
}
}
checkForDupIds(jsonObj1, "jsonObj1");
checkForDupIds(jsonObj2, "jsonObj2");
<html>
<body>
<div id='logger'></div>
</body>
</html>
You can loop over the array and keep a count of how many times each userId value appears. If you get to 2 for any value, stop and return false (or some other suitable value).
Array.prototype.some allows looping over the array until the condition is true, so it only loops over the source once. The data in the OP was invalid, I've modified it to be an array of objects.
var data = [{
"name":"John",
"age":30,
"userId": 5
},
{
"name":"Benjamin",
"age":17,
"userId": 5
},
{
"name":"Johnatan",
"age":35,
"userId": 10
}]
function hasDupIDs(data) {
// Store for userId values
var ids = {};
// Loop over values until condition returns true
return data.some(function(x) {
// If haven't seen this id before, add to ids
if (!ids.hasOwnProperty(x.userId)) ids[x.userId] = 0;
// Increment count
ids[x.userId]++;
// Return true if second instance
return ids[x.userId] > 1;
});
}
console.log(hasDupIDs(data));
If you want more concise code, you can use:
var data = [
{"name":"John","age":30,"userId": 5},
{"name":"Benjamin","age":17,"userId": 5},
{"name":"Johnatan","age":35,"userId": 10}];
function hasDupIDs(data) {
var ids = {};
return data.some(x => {
ids[x.userId] || (ids[x.userId] = 0);
return ++ids[x.userId] > 1;
});
}
console.log(hasDupIDs(data));
Related
I tried to create new array object from array , set rank according to its value . If value is the same, set the same rank and if next value is different set rank by skipping same rank length .
Expected result is
[
{
"rank": 1,
"data": 45
},
{
"rank": 2,
"data": 33
},
{
"rank": 3,
"data": 8
},
{
"rank": 4,
"data": 5
},
{
"rank": 4,
"data": 5
},
{
"rank": 6,
"data": 2
}
]
var data = [8,5,2,33,5,45];
var rankList = [];
var uniqueList = [];
var rank = 0;
var sameRank = 0;
data.sort(function(a,b) { return b - a; });
for(var i in data) {
if(uniqueList.includes(data[i])) {
rank++;
rankList.push({rank: sameRank, data: data[i]});
continue;
}
rank++;
sameRank++;
rankList.push({rank: rank, data: data[i]});
}
console.log(rankList);
Once you've sorted the array, create another array of objects with .map, keeping track of the last rank and data used. If the new data is the same, use the same rank (the one taken from a prior iteration) - otherwise, use the current iteration index plus 1:
const data = [8, 5, 2, 33, 5, 45];
data.sort((a, b) => b - a);
let lastRank = 0;
let lastData;
const output = data.map((data, i) => {
const objToReturn = { data };
objToReturn.rank = data === lastData ? lastRank : i + 1;
lastData = data;
lastRank = objToReturn.rank;
return objToReturn;
});
console.log(output);
Get the corresponding type in the object, and then traverse the array of push objects, but I can't think of a better way to solve the desired result below.
I want a good return as follows:
[{
"id": 1,
"type": "one",
"name": ["apple","apricot"]
},
{
"id": 3,
"type": "two",
"name": ["avocado"]
}]
var result = [{
"id": 1,
"type": "one",
"name": "apple"
}, {
"id": 2,
"type": "one",
"name": "apricot"
},
{
"id": 3,
"type": "two",
"name": "avocado"
}
]
Array.prototype.unique = function() {
var hash = {},
len = this.length,
result = [];
for (var i = 0; i < len; i++) {
if (!hash[this[i].type]) {
result.push(this[i].type);
hash[this[i].type] = true;
}
}
return result;
}
console.log(result)
console.log(result.unique())
var cArr = result.unique()
var arr = []
cArr.forEach(function(prop) {
result.map(function(item) {
if (prop == item.type) {
console.log(item)
arr.push({
...item,
[`user_${item.id}`]: item.user,
})
}
})
})
console.log(arr)
You can do this with reduce quite easily:
var input = [
{ id: 1, type: "one", name: "apple"},
{ id: 2, type: "one", name: "apricot" },
{ id: 3, type: "two", name: "avocado" }
];
// Make sure `unique` doesn't already exist on the Array prototype
if (!('unique' in Array.prototype)) {
Array.prototype.unique = function () {
// iterate over the array
const temp = this.reduce((acc, current) => {
// Desstructure the id, type, and name from the current object
const { id, type, name } = current;
// If an key with the value of `type` doesn't exist
// on the accumulator, add a new object with name set
// to an empty array
acc[type] = acc[type] || { id, type, name: [] };
// Push the name in the current object to the name array
acc[type].name.push(name);
// Return the accumulator for the next iteration
return acc;
// Note: the initial accumulator value is an object
}, {});
// Then simply return the values from the accumulated object
return Object.values(temp);
}
}
console.log(input.unique())
I have an array that looks like this:
var array = [[
{ "loc": {} },
{ "distance": 6.4 },
{ "zip1": "06120" },
{ "zip2": "06095" },
{ "group": 1 },
{ "weight": 1119 }
], [
{ "loc": {} },
{ "distance": 6.41 },
{ "zip1": "06095" },
{ "zip2": "06120" },
{ "group": 2 },
{ "weight": 41976 }
], [
{ "loc": {} },
{ "distance": 6.41 },
{ "zip1": "06095" },
{ "zip2": "06120" },
{ "group": 1 },
{ "weight": 41976 }
]];
Now I want to take the array values based on the property values for show in HTML.
Expected output is split into array with "group" property. I also need to store in HTML with based on group, as shown in the example below:
group 1:
all zip1's under group 1
group 2:
all zip1's under group 2
I tried using a loop but I didn't manage to get the right answer:
for (var k = 0; k < array.length; k++) {
var array1 = array[k];
if (flag[array1[2]["zip1"]]) continue;
flag[array1[2]["zip1"]] = true;
output2.push(array1);
}
So help me to find split the array show in HTML with group wise
Using reduce, you can create an object with each group value as key and an array of zip1 as values like this:
Then loop through the Object.entries, to create the HTML:
const array = [[{"loc":{}},{"distance":6.4},{"zip1":"06120"},{"zip2":"06095"},{"group":1},{"weight":1119}],[{"loc":{}},{"distance":6.41},{"zip1":"06095"},{"zip2":"06120"},{"group":2},{"weight":41976}],[{"loc":{}},{"distance":6.41},{"zip1":"06095"},{"zip2":"06120"},{"group":1},{"weight":41976}]];
const merged = array.reduce((r, a) =>{
const { group } = a.find(n => n.group)
const { zip1 } = a.find(n => n.zip1)
r[group] = r[group] || []
r[group].push(zip1)
return r;
},{})
const output = document.getElementById('output');
Object.entries(merged).forEach(([group, zips]) => {
const h1 = document.createElement('h1');
h1.innerHTML = "group " + group
const span = document.createElement('span');
span.innerHTML = `Zip1 - ${zips} (in group - ${group})`;
output.appendChild(h1)
output.appendChild(span)
})
<div id="output"></div>
Maybe this question has already been asked and answered somewhere but after searching for more than 3 hrs I'm asking this question.
Below is my JSON data
var my_data = [
{
"TempRture_qc": 4,
"VoltAGE": 44.09722,
"TempRture": 22.32,
"VoltAGE_qc": 55,
"_time": "2018-08-07T03:39:29.001Z"
},
{
"TempRture_qc": 2,
"VoltAGE": 42.09722,
"TempRture": 22.12,
"VoltAGE_qc": 0,
"_time": "2018-08-07T03:39:30.006Z"
},
{
"TempRture_qc": 1,
"VoltAGE": 43.09722,
"TempRture": 22.82,
"VoltAGE_qc": 0,
"_time": "2018-08-07T03:39:31.009Z"
}
];
desired output i need
[
{
"name": "TempRture_qc",
"data": [
{"name":"2018-08-07T03:39:29.001Z","y":4},
{"name":"2018-08-07T03:39:30.006Z","y":2},
{"name":"2018-08-07T03:39:33.017Z","y":1}
]
},
{
"name": "VoltAGE",
"data": [
{"name":"2018-08-07T03:39:29.001Z","y":44.09722},
{"name":"2018-08-07T03:39:30.006Z","y":42.09722},
{"name":"2018-08-07T03:39:33.017Z","y":43.09722}
]
},
{
"name": "TempRture",
"data": [
{"name":"2018-08-07T03:39:29.001Z","y":22.32},
{"name":"2018-08-07T03:39:30.006Z","y":22.12},
{"name":"2018-08-07T03:39:33.017Z","y":22.82}
]
},
{
"name": "VoltAGE_qc",
"data": [
{"name":"2018-08-07T03:39:29.001Z","y":55},
{"name":"2018-08-07T03:39:30.006Z","y":0},
{"name":"2018-08-07T03:39:33.017Z","y":0}
]
}
]
for getting this above output i have tried below code.
var accounting = [];
var fieldName = {};
for (var x in obj){
var mykey = Object.keys(obj[x]);
for (var mk in mykey){
if(mykey[mk]=='VoltAGE'){
fieldName.name = mykey[mk];
// accounting.push({
// "name":mykey[mk]
// })
}
if(mykey[mk]=='TempRture'){
fieldName.name = mykey[mk];
}
// console.log(mykey[mk]); //to get the key name
}
accounting.push({
"name" : obj[x]._time,
"y" : obj[x][employees.name],
})
fieldName.data = accounting;
}
console.log(fieldName );
by doing this what I'm getting is below JSON
{ name: 'TempRture',
data:
[ { name: '2018-08-07T03:39:29.001Z', y: 22.32 },
{ name: '2018-08-07T03:39:32.014Z', y: 22.12 },
{ name: '2018-08-07T03:39:33.017Z', y: 22.82 } ] }
I'm not able to understand how I will get the data in one JSON object.
For a solution with low time complexity, try .reduceing into an object indexed by keys of the inner object, creating a { name, data: [] } at that key in the accumulator if it doesn't exist there yet. Then, push to the data array, and get the values of the whole object:
var my_data=[{"TempRture_qc":4,"VoltAGE":44.09722,"TempRture":22.32,"VoltAGE_qc":55,"_time":"2018-08-07T03:39:29.001Z"},{"TempRture_qc":2,"VoltAGE":42.09722,"TempRture":22.12,"VoltAGE_qc":0,"_time":"2018-08-07T03:39:30.006Z"},{"TempRture_qc":1,"VoltAGE":43.09722,"TempRture":22.82,"VoltAGE_qc":0,"_time":"2018-08-07T03:39:31.009Z"}]
console.log(Object.values(
my_data.reduce((a, { _time, ...obj }) => {
Object.entries(obj).forEach(([name, val]) => {
if (!a[name]) a[name] = { name, data: [] };
a[name].data.push({ name: _time, y: val });
});
return a;
}, {})
));
var my_data=[{"TempRture_qc":4,"VoltAGE":44.09722,"TempRture":22.32,"VoltAGE_qc":55,"_time":"2018-08-07T03:39:29.001Z"},{"TempRture_qc":2,"VoltAGE":42.09722,"TempRture":22.12,"VoltAGE_qc":0,"_time":"2018-08-07T03:39:30.006Z"},{"TempRture_qc":1,"VoltAGE":43.09722,"TempRture":22.82,"VoltAGE_qc":0,"_time":"2018-08-07T03:39:31.009Z"}]
var keys = Object.keys(my_data[0])
var result= [];
for(i = 0; i<keys.length-1; i++) {
var obj = {name: keys[i],data: []}
obj.data = my_data.map(val=>({name: val["_time"], y: val[keys[i]]}));
result.push(obj);
}
console.log(result)
An understandable answer with map, findIndex and forEach functions will be
var my_data = [{ "TempRture_qc": 4, "VoltAGE": 44.09722, "TempRture": 22.32, "VoltAGE_qc": 55, "_time": "2018-08-07T03:39:29.001Z" }, { "TempRture_qc": 2, "VoltAGE": 42.09722, "TempRture": 22.12, "VoltAGE_qc": 0, "_time": "2018-08-07T03:39:30.006Z" }, { "TempRture_qc": 1, "VoltAGE": 43.09722, "TempRture": 22.82, "VoltAGE_qc": 0, "_time": "2018-08-07T03:39:31.009Z" } ],
result = [];
my_data.map(itm => {
let keys = Object.keys(itm);
keys.forEach(iitt => {
if (iitt != '_time') {
let index = result.findIndex(ii => {
return ii.name == iitt;
})
if (index == -1) {
result.push({
name: iitt,
data: []
});
result[result.length - 1].data.push({
name: itm["_time"],
y: itm[iitt]
})
} else {
result[index].data.push({
name: itm["_time"],
y: itm[iitt]
});
}
}
})
})
console.log(result)
I was looking for group by functionality over array of array and wrote something like,
var response = {
"data": {
"results": {
"facebook": [
[
"Campaign Name",
'promo',
'id'
],
[
"Sok_MPA_10Link_IntOnlineShoppingSites_1412",
"promo1",
4
],
[
"PPLA",
"promo1",
9
],
[
"PPLA",
"promo2",
90
],
[
"Sok_MPA_10Link_IntOnlineShoppingSites_1412",
"promo1",
45,
5
]
]
}
},
"exception": null,
"status": "OK",
"sokratiRequestId": null,
"json": null
};
var mapData = {};
$.map(response.data.results, function(value, key) {
headers = value.shift();
$.map(response.data.results[key], function(data) {
$.each(headers, function(index, column) {
if (index == headers.indexOf('id')) return true;
if (mapData[column] == undefined) {
mapData[column] = {};
}
if (mapData[column][data[index]] == undefined) {
mapData[column][data[index]] = 0;
}
mapData[column][data[index]] += data[headers.indexOf('id')]
});
});
console.log(mapData)
});
Basically I want to group over multiple fields in the array - Like ["Campaign Name" & promo']
Any good way to achieve it?
Output should be -
"Campaign Name": {
PPLA: 99
Sok_MPA_10Link_IntOnlineShoppingSites_1412: 49
},
"promo": {
promo1: 58
promo2: 90
}
https://jsfiddle.net/ezg8Lzdr/
Note
Answer should purely be in JS - No other frameworks [No lodash]
Edit:
With Array.prototype.reduce() and an object for the result. The given groups items are taken either for the group property and their index for the wanted data part to get a sub property.
var response = { "data": { "results": { "facebook": [["Campaign Name", 'promo', 'id'], ["Sok_MPA_10Link_IntOnlineShoppingSites_1412", "promo1", 4], ["PPLA", "promo1", 9], ["PPLA", "promo2", 90], ["Sok_MPA_10Link_IntOnlineShoppingSites_1412", "promo1", 45, 5]] } }, "exception": null, "status": "OK", "sokratiRequestId": null, "json": null },
data = response.data.results.facebook,
result = {},
groups = data.shift();
groups.pop();
result = data.reduce(function (r, a) {
groups.forEach(function (b, i) {
r[b] = r[b] || {};
r[b][a[i]] = (r[b][a[i]] || 0) + a[2];
});
return r;
}, {});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
I wrote a small function on JS that might help you:
function groupBy(collection, property) {
var i = 0, val, index,
values = [], result = [];
for (; i < collection.length; i++) {
val = collection[i][property];
index = values.indexOf(val);
if (index > -1)
result[index].push(collection[i]);
else {
values.push(val);
result.push([collection[i]]);
}
}
return result;
};
The use is simple:
groupBy(myArray, "facebook");
If the data schema is pretty much fixed:
var response = {
"data": {
"results": {
"facebook": [
[
"Campaign Name",
'promo',
'id'
],
[
"Sok_MPA_10Link_IntOnlineShoppingSites_1412",
"promo1",
4
],
[
"PPLA",
"promo1",
9
],
[
"PPLA",
"promo2",
90
],
[
"Sok_MPA_10Link_IntOnlineShoppingSites_1412",
"promo1",
45,
5
]
]
}
},
"exception": null,
"status": "OK",
"sokratiRequestId": null,
"json": null
};
var face = response.data.results.facebook;
//remove first row which is a schema
face.shift();
//take in index of column, return grouped sum
var reduce = function(index) {
return face.reduce((t, a) => {
t[a[index]] = (t[a[index]] || 0) + a[2];
return t;
}, {});
}
//final result
var result = {
"Campaign Name": reduce(0),
"promo": reduce(1)
}
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
For such basic operations on arrays, collection or whatever in JavaScript, I would recommend to use frameworks like lodash which is full of tricks like this one you will need everywhere in your project:
https://lodash.com/docs#groupBy
The most common way is to use library to data manipulation like https://lodash.com/
Using this library you can group your data like this:
var result = _.chain(data)
.groupBy("color")
.pairs()
.map(function(currentItem) {
return _.object(_.zip(["color", "users"], currentItem));
})
.value();