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);
Related
I have an array of object :
let data = [
{ "date" : "17/03/2022", "count" : 2, "james#email.net" : 2 },
{
"date" : "17/05/2022",
"count" : 2,
"admin#email.com" : 1,
"secretary#email.uk" : 1
},
{ "date" : "17/07/2022", "count" : 7, "staff#email.us" : 7 },
];
I would like to remove "#" in the object key instead of the email address.
This is the expected output :
// Expected output:
data = [
{ "date" : "17/03/2022", "count" : 2, "james" : 2 },
{
"date" : "17/05/2022",
"count" : 2,
"admin" : 1,
"secretary" : 1
},
{ "date" : "17/07/2022", "count" : 7, "staff" : 7 },
];
Notes:
james is from james#email.net (1st element)
admin and secretary are from admin#email.com and secretary#email.uk, respectively (2nd element)
staff is from staff#email.us (3rd element)
and so on.
email as object keys are dynamic, meaning it can be "johndoe#email.co.uk", "mary#email.net", etc.
I have tried, but yet not successful :
for (let i = 0; i < data.length; i++) {
let keys = Object.keys(data[i]);
console.log(`key-${i+1} :`, keys); // [ 'date', 'count', 'admin#email.com', 'secretary#email.uk' ]
let emails = keys.filter(index => index.includes("#"));
console.log(`email-${i+1} :`, emails); // [ 'admin#email.com', 'secretary#email.uk' ]
let nameList = [];
for (let i = 0; i < emails.length; i++) {
let name = emails[i].split("#")[0];
nameList.push(name);
}
console.log(`name-${i+1} :`, nameList); // [ 'admin', 'secretary' ]
}
Thanks in advance.
You could create a function which splits the keys of the object keys at # and creates a new object using Object.fromEntries().
Here's a snippet:
const data = [{date:"17/03/2022",count:2,"james#email.net":2},{date:"17/05/2022",count:2,"admin#email.com":1,"secretary#email.uk":1},{date:"17/07/2022",count:7,"staff#email.us":7}];
const converter = o => Object.fromEntries(
Object.entries(o).map(([k, v]) => [k.split("#")[0], v])
)
console.log(
data.map(converter)
)
If Object.fromEntries() is not supported, you could use a simple loop through the array and then each object to create new objects like this:
const output = []
for (const o of data) {
const updated = {}
for (const key in o) {
updated[key.split("#")[0]] = o[key]
}
output.push(updated)
}
Try this as short as simple:
let data = [{
"date": "17/03/2022",
"count": 2,
"james#email.net": 2
},
{
"date": "17/05/2022",
"count": 2,
"admin#email.com": 1,
"secretary#email.uk": 1
},
{
"date": "17/07/2022",
"count": 7,
"staff#email.us": 7
},
];
const refinedData = JSON.parse(JSON.stringify(data));
refinedData.map((el, i) => {
Object.keys(el).map(e => {
if(e.includes('#')){
refinedData[i][e.slice(0, e.indexOf('#'))] = refinedData[i][e];
delete refinedData[i][e];
}
})
});
console.log(data, refinedData);
Try this improvement to prevent shallow copy and let me know your thoughts.
Can you try using this?
for (let i = 0; i < data.length; i++) {
let element = data[i];
let keys = Object.keys(element);
let emails = keys.filter(index => index.includes("#"));
for (let j = 0; j < emails.length; j++) {
let name = emails[j].split("#")[0];
let value = element[emails[j]];
Object.defineProperty(element, name, { value });
delete element[emails[j]];
}
}
console.log(data);
I have the following array. I am trying to get the element having maximum id by grouping by the entryId in node.js.
[
{
"entryId": "7wpNAXhYI",
"id": 5
},
{
"entryId": "7wpNAXhYI",
"id": 6
},
{
"entryId": "5PGB23RI",
"id": 7
},
{
"entryId": "5PGB23RI",
"id": 8
}
]
The typical sql syntax would like as follows:
select entryId, max(id) from table group by entryId
I have written the following code which would get just the max without grouping by. Any help how to modify the following code or any simple approach available.
function getMax(array) {
var max = {};
for (var i = 0; i < array.length; i++) {
if (parseInt(array[i].id) > (parseInt(max.id) || 0))
max = array[i];
}
return max;
}
You can use sort in descending order and return the first element
var a = [{
"entryId": "7wpNAXhYI",
"id": 5
},
{
"entryId": "7wpNAXhYI",
"id": 6
},
{
"entryId": "5PGB23RI",
"id": 7
},
{
"entryId": "5PGB23RI",
"id": 8
}
]
function getMax(array) {
return array.sort((a, b) => b.id - a.id)[0]
}
console.log(getMax(a));
You can use 2 reduce the first one is to group the array. The second one is to get the max using Math.max()
var arr = [{"entryId":"7wpNAXhYI","id":5},{"entryId":"7wpNAXhYI","id":6},{"entryId":"5PGB23RI","id":7},{"entryId":"5PGB23RI","id":8}]
var result = Object.entries(arr.reduce((c, {entryId,id}) => {
(c[entryId] = c[entryId] || []).push(id);
return c;
}, {})).reduce((c, [k, v]) => Object.assign(c, {[k]: Math.max(...v)}), {});
console.log(result);
You can use map if you prefer an array:
var arr = [{"entryId":"7wpNAXhYI","id":5},{"entryId":"7wpNAXhYI","id":6},{"entryId":"5PGB23RI","id":7},{"entryId":"5PGB23RI","id":8}]
var result = Object.entries(arr.reduce((c, {entryId,id}) => {
(c[entryId] = c[entryId] || []).push(id);
return c;
}, {})).map(([entryId, id]) => ({entryId,id: Math.max(...id)}))
console.log(result);
You can use reduce to get the maximum.
function getMax(arr) {
max = arr.reduce((M, o) => M > o.id ? M : o, {id:-Infinity});
}
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>
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));
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
How can I make this
var foo = [{
"number":[1, 2, 3],
"id": [81, 82, 83]
}];
Into this
var foo = [{
"number": 1,
"id": 81
},{
"number": 2,
"id": 82
},{
"number": 3,
"id": 83
}]
I tried .map() and .filter() but they don't turn out the way I need it. Any suggestions? Thanks
You could create a function for that:
function transform(values) {
const result = [];
values.forEach(value => {
value.id.forEach((id, i) => {
result.push({id, number: value.number[i]});
});
});
return result;
}
While I find this to be an odd question, and I'm still hoping for a response regarding my suspicion this is an XY problem, here is a possible approach you can use for whatever you're trying to do.
Let's assume that foo is a single object which only contains enumerable properties that are all arrays of equal length:
var foo = {
"number": [1, 2, 3],
"id": [81, 82, 83]
}
function spread(obj) {
// get the enumerable keys of your object
var keys = Object.keys(obj)
// initialize an empty array
var array = []
// for each key...
keys.forEach(function (key) {
// for each element in the array of the property...
obj[key].forEach(function (value, index) {
// if the array element does not contain an object
// initialize an empty object in index
var base = index < array.length ? array[index] : (array[index] = {})
// assign the value to the key in the element
base[key] = value
})
})
// return the generated array
return array
}
console.log(spread(foo))
You can map the array's object, and thee number array of each object into a new array, then concat the results to flatten the sub arrays into one array.
var foo = [{
"number":[1, 2, 3],
"id": [81, 82, 83]
}];
var result = [].concat.apply([], foo.map(function(obj) { // map the array into sub arrays and flatten the results with concat
return obj.number.map(function(n, i) { // map the number array
return {
number: n,
id: obj.id[i] // get the id value by using the index
};
})
}));
console.log(result);
You need to create a list of objects based on the number of values within a given key.
So, you need to loop over the main list of objects. Inside that loop, you need to loop over the values for a key (i.e. pick the first). You will not need to use these values directly, they are just to determine how many records will be created in the final array. Lastly, you just iterate over the keys again and map the key-values pairs based on the current index.
The Array.prototype.concat.apply([], ...arrays) that happens at the end will combine all the arrays.
The function supports a single object or a list of objects.
var foo = [{
"number" : [ 1, 2, 3],
"id" : [81, 82, 83]
}, {
"number" : [ 4, 5, 6],
"id" : [84, 85, 86]
}];
console.log(JSON.stringify(mapValues(foo), null, 4));
function mapValues(arr) {
arr = !Array.isArray(arr) ? [arr] : arr;
return Array.prototype.concat.apply([], arr.map(item => {
return item[Object.keys(item)[0]].map((val, index) => {
return Object.keys(item).reduce((obj, key) => {
obj[key] = item[key][index];
return obj;
}, {});
});
}));
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
Here is another version that does not introduce much complexity.
var foo = [{
"number" : [1, 2, 3],
"id" : [81, 82, 83]
}, {
"number" : [4, 5, 6],
"id" : [84, 85, 86]
}];
console.log(JSON.stringify(mapValues(foo), null, 4));
function mapValues(arr) {
arr = !Array.isArray(arr) ? [arr] : arr;
let records = [], fields;
arr.forEach(item => {
fields = fields || Object.keys(item);
item[fields[0]].forEach((val, index) => {
records.push(fields.reduce((obj, key) => {
obj[key] = item[key][index];
return obj;
}, {}));
});
});
return records;
}
.as-console-wrapper {
top: 0;
max-height: 100% !important;
}
Result
[{
"number": 1,
"id": 81
}, {
"number": 2,
"id": 82
}, {
"number": 3,
"id": 83
}, {
"number": 4,
"id": 84
}, {
"number": 5,
"id": 85
}, {
"number": 6,
"id": 86
}]