Form into a single array after iterating an object - javascript

How to get values of views into single array and get the two largest values in that array. The below is not creating single array. Could someone please advise ?
const data = [
{
id: 1,
views: 5678,
textData: "Sun"
},
{
id: 2,
views: 2500,
textData: "Moon"
},
{
id: 3,
views: 3500,
textData: "Earth"
},
{
id: 4,
views: 1250,
textData: "Sky"
}
]
data.map(({id, views, textData}) =>{
let myArr = [];
myArr.push(views);
let result = Math.max(...myArr);
console.log(result);
})
Desired Array: [5678, 2500, 3500, 1250 ]
Final Output : [5678,3500 ]

You can use Array#map to create an array of the views properties, then sort it.
const data=[{id:1,views:5678,textData:"Sun"},{id:2,views:2500,textData:"Moon"},{id:3,views:3500,textData:"Earth"},{id:4,views:1250,textData:"Sky"}];
let res = data.map(x => x.views).sort((a,b) => b - a).slice(0, 2);
console.log(res);

Get result in one loop without sorting, but the code doesn't look very clean.
const data=[{id:1,views:5678,textData:"Sun"},{id:2,views:2500,textData:"Moon"},{id:3,views:3500,textData:"Earth"},{id:4,views:1250,textData:"Sky"}];
const values1 = []
const values2 = [0, 0]
data.forEach(d => {
values1.push(d.views)
values2[0] = Math.max(values2[0], Math.min(d.views, values2[1]))
values2[1] = Math.max(d.views, values2[1])
})
console.log('single values: ', values1)
console.log('two largest values: ', values2)

Related

Improve nested forEach

I have this nested array:
const users = [
['User_1', [[1596232800000, 4]]],
[
'User_2',
[
[1591567200000, 3],
[1591653600000, 16],
],
],
]
and would like this output:
const dataByDate = [
{
user: 'User_2',
date: 1591567200000,
count: 3,
},
{
user: 'User_2',
date: 1591653600000,
count: 16,
},
{
user: 'User_1',
date: 1596232800000,
count: 4,
},
]
To achieve this I am doing this:
const dataByDate: { date: string; count: number; user: string }[] = []
users.forEach((user: string[]) => {
if (user[1].length) {
user[1].forEach((item: any) => {
dataByDate.push({ date: item[0], user: user[0], count: item[1] })
})
}
})
My solution works fine but I am wondering if there is a cleaner and more elegant solution than a nested forEach. Thanks!
You can use .flatMap with an inner .map(). The inner .map() will take the second element of your inner array (ie: the [[date, count], ...] arrays), and map them to objects. Since .map() will result in an array of objects, you can use .flatMap() to merge the resulting objects into one final resulting array.
See example below:
const users = [
['User_1', [[1596232800000, 4]]],
[
'User_2',
[
[1591567200000, 3],
[1591653600000, 16],
],
],
];
const result = users.flatMap(([user, arr]) => arr.map(([date, count]) => ({
user, date, count
})));
console.log(result);
You can then apply the .sort() method for any additional reordering of the output array.
Use a combination of Array.prototype.flatMap() and Array.prototype.reduce(). The reduce loops over each data set for a user and creates and object per entry in that set. That object is then combined in the accumulating array.
Now flatMap returns a new array with objects for each user. The amount of objects are dependant on the amount of [date, count] entries and will be in a nested array. The flat part of flatMap takes care of this by putting every object in a single array.
const users = [
[
'User_1', [
[1596232800000, 4]
]
],
[
'User_2', [
[1591567200000, 3],
[1591653600000, 16],
],
],
];
const formatUserData = users => users.flatMap(([ user, data ]) =>
data.reduce((arr, [ date, count ]) =>
[...arr, { user, date, count }], [])
);
const result = formatUserData(users);
console.log(result);
Using map and array destructuring, you can achieve this as:
const result = users
.map(([ user, items ]) => {
return items.flatMap(([date, count]) => ({ user, date, count }))
})
.flatMap(i => i)
.sort((a,b) => a.date - b.date);
const users = [
['User_1', [[1596232800000, 4]]],
[
'User_2',
[
[1591567200000, 3],
[1591653600000, 16],
],
],
]
const result = users.map(([ user, items ]) => {
return items.flatMap(([date, count]) => ({ user, date, count }))
}).flatMap(i => i).sort((a,b) => a.date - b.date);
console.log({result})

Converted an Object with keys from multiple array for sorting and now want them back as arrays as they are in sorted

var values =selectValues;
var names = selectNames;
var priorities = prioritizedHours;
var prefers = preferHrsArray;
var years = workedYearsArray;
var items = values.map((value, index) => {
return {
value: value,
name: names[index],
priority: priorities[index],
prefer: prefers[index],
year: years[index]
}
});
var arrayObject = JSON.stringify(items);
Logger.log('Object array: '+arrayObject);
In the above program, I am creating an object from the arrays such as names, priorities, and so on. Resulting Object is following after I have made a sorting of them:
[
{"value":1,"name":"Fiona","prefer":30,"year":6},
{"value":1,"name":"Martin","prefer":40,"year":7},
{"value":2,"name":"Adam","prefer":0,"year":20},
{"value":2,"name":"Steve","prefer":100,"year":5}
]
Now as sorting is done, I want the arrays back as they are in the Object.
I am trying to get arrays like:
value = [1,1,2,2],
name = ['Fiona', 'Martin','Adam', 'Steve'],
prefer = [30,40,0,100],
year = [6,7,20,5]
Thank you for helping me out.
You can use forEach for this case
const array = [
{"value":1,"name":"Fiona","prefer":30,"year":6},
{"value":1,"name":"Martin","prefer":40,"year":7},
{"value":2,"name":"Adam","prefer":0,"year":20},
{"value":2,"name":"Steve","prefer":100,"year":5}
]
const values = []
const names = []
const prefers = []
const years = []
array.forEach(rec => {
values.push(rec.value),
names.push(rec.name),
prefers.push(rec.prefer),
years.push(rec.year)
})
console.log(values)
console.log(names)
console.log(prefers)
console.log(years)
Map should work:
const data = [
{ value: 1, name: "Fiona", prefer: 30, year: 6 },
{ value: 1, name: "Martin", prefer: 40, year: 7 },
{ value: 2, name: "Adam", prefer: 0, year: 20 },
{ value: 2, name: "Steve", prefer: 100, year: 5 },
];
const values = data.map(x=>x.value);
const names = data.map(x=>x.name);
console.log(values, names);
//[ 1, 1, 2, 2 ] [ 'Fiona', 'Martin', 'Adam', 'Steve' ]
See MDN for details of map
You could also make it a little more dynamic by using reduce and then only getting the lists you want using Object destructuring.
const arr = [
{"value":1,"name":"Fiona","prefer":30,"year":6},
{"value":1,"name":"Martin","prefer":40,"year":7},
{"value":2,"name":"Adam","prefer":0,"year":20},
{"value":2,"name":"Steve","prefer":100,"year":5}
];
const {name, value, prefer, year} = arr.reduce((acc, curr) => {
Object.entries(curr).forEach(([key, val]) => {
if(acc[key] == null)
acc[key] = [];
acc[key].push(val);
});
return acc;
}, {})
console.log(name);
console.log(value);
console.log(prefer);
console.log(year);

How to dedupe an array of objects by a key value pair?

// This is a large array of objects, e.g.:
let totalArray = [
{"id":"rec01dTDP9T4ZtHL4","fields":
{"user_id":170180717,"user_name":"abcdefg","event_id":516575,
}]
let uniqueArray = [];
let dupeArray = [];
let itemIndex = 0
totalArray.forEach(x => {
if(!uniqueArray.some(y => JSON.stringify(y) === JSON.stringify(x))){
uniqueArray.push(x)
} else(dupeArray.push(x))
})
node.warn(totalArray);
node.warn(uniqueArray);
node.warn(dupeArray);
return msg;
I need my code to identify duplicates in the array by a key value of user_id within the objects in the array. Right now, my code works to identify identical objects in the array, but I need it to identify dupes based on a key value inside the objects instead. How do I do this? I am struggling to figure out how to path the for each loop to identify the dupe based on the key value instead of the entire object.
Right now, my code works to identify identical objects in the array, but I need it to identify dupes based on a key value inside the objects instead. How do I do this?
Don’t compare the JSON representation of the whole objects then, but only their user_id property specifically.
totalArray.forEach(x => {
if(!uniqueArray.some(y => y.fields.user_id === x.fields.user_id)){
uniqueArray.push(x)
} else(dupeArray.push(x))
})
You could take a Set and push to either uniques or duplicates.
var array = [
{ id: 1, data: 0 },
{ id: 2, data: 1 },
{ id: 2, data: 2 },
{ id: 3, data: 3 },
{ id: 3, data: 4 },
{ id: 3, data: 5 },
],
uniques = [],
duplicates = [];
array.forEach(
(s => o => s.has(o.id) ? duplicates.push(o) : (s.add(o.id), uniques.push(o)))
(new Set)
);
console.log(uniques);
console.log(duplicates);
.as-console-wrapper { max-height: 100% !important; top: 0; }
One way is to keep a list of ids you found so far and act accordingly:
totalArray = [
{ id: 1, val: 10 },
{ id: 2, val: 20 },
{ id: 3, val: 30 },
{ id: 2, val: 15 },
{ id: 1, val: 50 }
]
const uniqueArray = []
const dupeArray = []
const ids = {}
totalArray.forEach( x => {
if (ids[x.id]) {
dupeArray.push(x)
} else {
uniqueArray.push(x)
ids[x.id] = true
}
})
for (const obj of uniqueArray) console.log("unique:",JSON.stringify(obj))
for (const obj of dupeArray) console.log("dupes: ",JSON.stringify(obj))

How to set array key as it's index in javascript/node js

I have an array of objects like this :
var kvArray = [
{
number: '123',
duration: '00:00:00'
},
{
number: '324',
duration: '00:00:00'
}]
I want to generate a new array from the above array such that the number key becomes the index.
This is what I tried
var kvArray = [
{
number: '123',
duration: '00:00:00'
},
{
number: '324',
duration: '00:00:00'
}]
var reformattedArray = kvArray.map(obj =>{
var rObj = {};
rObj[obj.number] = obj.duration;
return rObj;
});
console.log(reformattedArray)
The above output looks like this in the console with 0 and 1 as the index:
Instead I want the output array to be like this :
123: {"00:00:00"}
324: {"00:00:00"}
such that instead of 0 , 1 as the index I have 123 and 324 as the index.
So that if write test_array[123] in my code I should be able to get 00:00:00 in the output. Is it possible to achieve what I'm trying to do here?
Suggest better ways how this can be done
How do I do this?
You can use array#map with Object.assign() to create the desired output.
const data = [ { number: '123', duration: '00:00:00' }, { number: '324', duration: '00:00:00' } ],
result = Object.assign(...data.map(({number, duration}) => ({[number]: duration})));
console.log(result);
In case number values will be unique in your array, you can use .reduce() to create a map object like shown below:
const data = [
{ number: '123', duration: '00:00:00' },
{ number: '324', duration: '00:00:00' }
];
const map = data.reduce((r, { number:k, duration:v }) => (r[k] = v, r), {});
console.log(map);
reformattedArray =[]
tempHash = kvArray.reduce(function(i,j){
return $.extend(i,j)
})
for(i in tempHash) {
reformattedArray[i] = tempHash[i]
}

how to count duplicate values object to be a value of object

how to count the value of object in new object values
lets say that i have json like this :
let data = [{
no: 3,
name: 'drink'
},
{
no: 90,
name: 'eat'
},
{
no: 20,
name: 'swim'
}
];
if i have the user pick no in arrays : [3,3,3,3,3,3,3,3,3,3,3,90,20,20,20,20]
so the output should be an array
[
{
num: 3,
total: 11
},
{
num: 90,
total: 1
},
{
num:20,
total: 4
}
];
I would like to know how to do this with a for/of loop
Here is the code I've attempted:
let obj = [];
for (i of arr){
for (j of data){
let innerObj={};
innerObj.num = i
obj.push(innerObj)
}
}
const data = [{"no":3,"name":"drink"},{"no":90,"name":"eat"},{"no":20,"name":"swim"}];
const arr = [3,3,3,3,3,3,3,3,3,3,3,20,20,20,20,80,80];
const lookup = {};
// Loop over the duplicate array and create an
// object that contains the totals
for (let el of arr) {
// If the key doesn't exist set it to zero,
// otherwise add 1 to it
lookup[el] = (lookup[el] || 0) + 1;
}
const out = [];
// Then loop over the data updating the objects
// with the totals found in the lookup object
for (let obj of data) {
lookup[obj.no] && out.push({
no: obj.no,
total: lookup[obj.no]
});
}
document.querySelector('#lookup').textContent = JSON.stringify(lookup, null, 2);
document.querySelector('#out').textContent = JSON.stringify(out, null, 2);
<h3>Lookup output</h3>
<pre id="lookup"></pre>
<h3>Main output</h3>
<pre id="out"></pre>
Perhaps something like this? You can map the existing data array and attach filtered array counts to each array object.
let data = [
{
no: 3,
name: 'drink'
},
{
no:90,
name: 'eat'
},
{
no:20,
name: 'swim'
}
]
const test = [3,3,3,3,3,3,3,3,3,3,3,90,20,20,20,20]
const result = data.map((item) => {
return {
num: item.no,
total: test.filter(i => i === item.no).length // filters number array and then checks length
}
})
You can check next approach using a single for/of loop. But first I have to create a Set with valid ids, so I can discard noise data from the test array:
const data = [
{no: 3, name: 'drink'},
{no: 90, name: 'eat'},
{no: 20, name: 'swim'}
];
const userArr = [3,3,3,3,3,3,3,3,7,7,9,9,3,3,3,90,20,20,20,20];
let ids = new Set(data.map(x => x.no));
let newArr = [];
for (i of userArr)
{
let found = newArr.findIndex(x => x.num === i)
if (found >= 0)
newArr[found].total += 1;
else
ids.has(i) && newArr.push({num: i, total: 1});
}
console.log(newArr);

Categories