Array Sort by time hh:mm:ss - javascript

I am trying to sort the time. but I am unable to sort by time (hh:mm:ss) format. so i have used moments js. my array sort by time not get sorted. how sort array by using maps
I have an array of objects:
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
let parsedDates = new Map(
elements.map(e =>[["id", "date"],[e.id, moment(e.date, 'hh:mm:ss')]])
);
elements.sort((a, b) => parsedDates.get(a) - parsedDates.get(b));
console.log(elements.map(e => ({ id: e.id, date: e.date })));

You can lexicographical sort the time using string.localeCompare().
let times = [ { "id": 1, "date": "02:01:02" }, { "id": 2, "date": "01:01:01" }, { "id": 3, "date": "03:01:01" }, { "id": 4, "date": "04:01:01" } ];
times.sort((a,b) => a.date.localeCompare(b.date));
console.log(times);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can try this
function convertDateObj(hhmmss){
let obj = new Date();//creates a Date Object using the clients current time
let [hours,minutes,seconds] = hhmmss.split(':');
obj.setHours(+hours); // set the hours, using implicit type coercion
obj.setMinutes(minutes); //you can pass Number or String, it doesn't really matter
obj.setSeconds(seconds);
return obj;
}
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
elements.sort((a, b) => convertDateObj(a.date) - convertDateObj(b.date)); // Ascending order
elements.sort((a, b) => convertDateObj(b.date) - convertDateObj(a.date)); // Descending order

The parsedDates map you've created is looking like:
Map {
[ 'id', 'date' ] => [ 1, <some Date object> ],
[ 'id', 'date' ] => [ 2, <some Date object> ],
[ 'id', 'date' ] => [ 3, <some Date object> ],
[ 'id', 'date' ] => [ 4, <some Date object> ]
}
And then you try to extract from it with elements like this:
parsedDates.get({ "id": 1, "date": "02:01:02" })
This should not work, because the key in a Map is and Array instance.
Even if you were using an array as a key:
parsedDates.get([ 1, "02:01:02" ])
this still wouldn't work, as this would be a different Object reference. I mean two arrays
a = [ 1, "02:01:02" ]
b = [ 1, "02:01:02" ]
are stored in different places and are different Objects, even though their values are identical.
So, you can modify your solution a bit:
let elements =[
{
"id": 1,
"date": "02:01:02"
},
{
"id": 2,
"date": "01:01:01"
},
{
"id": 3,
"date": "03:01:01"
},
{
"id": 4,
"date": "04:01:01"
}
];
let parsedDates = new Map(
elements.map(e => [e.date, e])
);
elements = elements.map(x => x.date).sort().map(x => parsedDates.get(x))
console.log(elements)
// [
// { id: 2, date: '01:01:01' },
// { id: 1, date: '02:01:02' },
// { id: 3, date: '03:01:01' },
// { id: 4, date: '04:01:01' }
// ]

Related

How to combine my array and json result in one?

I want to combine two json results, but im struggling getting it done..
first one (galleryData):
[
{ "userId": 2, "profile": { "profileImage": "image" } },
{ "userId": 4, "profile": { "profileImage": "image" } },
]
second one (combinations):
{
data: [
{ round: 1, partner: 2 },
{ round: 2, partner: 4 }
]
}
the output im expecting:
{
data: [
{ round: 1, userId: 2, "profile": { "profileImage": "image" } },
{ round: 2, userId: 4, "profile": { "profileImage": "image" } }
]
}
Basically I need the profileImage from one of my result and map it to the correct user id
What I tried so far with no success:
let combinedResult = galleryData["userId"].map((item, i) => Object.assign({}, item, combinations[i]));
You can use map and on each callback use find to find the corresponding userId === partner
const galleryData = [
{ "userId": 2, "profile": { "profileImage": "image" } },
{ "userId": 4, "profile": { "profileImage": "image" } },
]
const combinations = {
data: [
{ round: 1, partner: 2 },
{ round: 2, partner: 4 }
]
}
let combinedResult = {
data: galleryData.map((item, i) => {
let combination = combinations.data.find(c => c.partner === item.userId);
return { ...item, round: combination.round }
})
};
console.log(combinedResult)
I think a little try using Array.forEach and then merge the Objects
a = [
{ "userId": 2, "profile": { "profileImage": "image" } },
{ "userId": 4, "profile": { "profileImage": "image" } },
]
b = {
data: [
{ round: 1, partner: 2 },
{ round: 2, partner: 4 }
]
}
// inside forEach you can write the logic to get elements from array 'a' as you can use `find` to check which user is needed
b.data.forEach((i,e) => { b.data[e] = {...i, ...a[e]} })
console.log(b)
Hope it will be helpful.
let galleryData = [
{ "userId": 2, "profile": { "profileImage": "image" } },
{ "userId": 4, "profile": { "profileImage": "image" } },
];
let galleryDataAsUserId = {};
galleryData.forEach(elem=>{
galleryDataAsUserId[elem.userId] = elem;
})
let combinations = {
data: [
{ round: 1, partner: 2 },
{ round: 2, partner: 4 }
]
};
let data = combinations.data;
data.map(elem=>{
let newElem = elem;
newElem.profile = galleryDataAsUserId[elem.partner].profile;
});
console.log(data)

Change structure of existing array

Hi I want to convert an array into another structure. Here is the original array.
[{"level1_label":"Branch 1","data":[{"count":"3","level2_label":"2021-11-11"}]},{"level1_label":"branch 2","data":[{"count":"1","level2_label":"2021-11-25"}]}]
I want to convert this array into
[
['Branch 1', '3', 2021 - 11 - 11],
['branch 2', '1', 2021 - 11 - 25]
];
Instead of using map I would suggest just iterating:
const data = [{
"level1_label": "Branch 1",
"data": [{
"count": "3",
"level2_label": "2021-11-11"
}]
}, {
"level1_label": "branch 2",
"data": [{
"count": "1",
"level2_label": "2021-11-25"
}]
}];
const result = [];
data.forEach(l1 => {
const lev2Arr = [l1.level1_label];
l1.data.forEach(l2 => {
lev2Arr.push(l2.count);
lev2Arr.push(l2.level2_label);
});
result.push(lev2Arr);
});
console.log(result);

Create an array of objects recursively based in array of objects

I have an array of objects like this:
myArr = [
{ "id": "aaa.bbb" },
{ "id": "aaa.ccc" },
{ "id": "111.222" },
{ "id": "111.333" },
]
My goal is to be able to have a new array for every part of the Id, while nesting the old array. Like this:
newArray = [
{
"id": "aaa",
"children": [{ "id": "aaa.bbb" }]
},
{
"id": "aaa",
"children": [{ "id": "aaa.ccc" }]
},
{...}
]
The idea is to be able to do It with multiple substrings if there is a bigger Id
You could use map to iterate through the array and mutate the objects in place
myArr = [ { "id": "aaa.bbb" }, { "id": "aaa.ccc" }, { "id": "111.222" }, { "id": "111.333" }, ]
result=myArr.map((o)=>({["id"]:o.id.split(".")[0],["children"]:[o]}))
console.log(result)
alternatively you could use reduce
myArr = [ { "id": "aaa.bbb" }, { "id": "aaa.ccc" }, { "id": "111.222" }, { "id": "111.333" }, ]
result=myArr.reduce((acc,curr)=>acc=[...acc,{["id"]:curr.id.split(".")[0],["children"]:[curr]}],[])
console.log(result)
Use Array.prototype.map.
const newArray = myArr.map( function( e ) {
const oldId = e.id;
const newElement = {
id: oldId.split( '.' )[0],
children: [ e ]
};
return newElement
} );
Simplified:
const newArray = myArr.map( function( e ) {
return {
id: e.id.split( '.' )[0],
children: [ e ]
};
} );
Further:
const newArray = myArr.map( e => { id: e.id.split( '.' )[0], children: [ e ] } );

How to group from array object

I using code form "
I am looking for best ways of doing this. I have group:
data
[
{
"date": "16/04/2020",
"count": 0,
"name": "A"
},
{
"date": "16/04/2020",
"count": 1,
"name": "B"
},
{
"date": "17/04/2020",
"count": 0,
"name": "B"
}
//...More.....
]
Answer
{
"date": "04/2020",
"symtom": {
"data": [
{
"date": "16/04/2020",
"data": [
{
"name": "A",
"count": [
{
"date": "16/04/2020",
"count": 0,
"name": "A"
}
]
},
{
"name": "B",
"count": [
{
"date": "16/04/2020",
"count": 1,
"name": "B"
}
]
},
//...More.....
]
},
{
"date": "17/04/2020",
"data": [
{
"name": "B",
"count": [
{
"date": "17/04/2020",
"count": 0,
"name": "B"
}
]
},
//...More.....
]
}
]
}
}
Can I fix the code and to get the desired answer?
Code :
const items = [
{
tab: 'Results',
section: '2017',
title: 'Full year Results',
description: 'Something here',
},
{
tab: 'Results',
section: '2017',
title: 'Half year Results',
description: 'Something here',
},
{
tab: 'Reports',
section: 'Marketing',
title: 'First Report',
description: 'Something here',
}
];
function groupAndMap(items, itemKey, childKey, predic){
return _.map(_.groupBy(items,itemKey), (obj,key) => ({
[itemKey]: key,
[childKey]: (predic && predic(obj)) || obj
}));
}
var result = groupAndMap(items,"tab","sections",
arr => groupAndMap(arr,"section", "items"));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
ref : Group array of object nesting some of the keys with specific names
But I would like to have the answer line this (Answer) :
{
"date": "04/2020",
"symtom": {
"data": [
{
"date": "16/04/2020",
"data": [
{
"name": "A",
"count": 0,
},
{
"name": "B",
"count": 1,
},
//...More.....
]
},
{
"date": "17/04/2020",
"data": [
{
"name": "B",
"count":0,
},
//...More.....
]
}
]
}
}
Thanks!
I am a beginner but it looks like you want system.data.data to = an array of objects with the keys name:str and count:number but instead you are applying the whole object into count so the key count:{name:A, count:0,date:etc}.
I really can't follow your function which separates the data... but all you should have to do is when count is sent the object to reference just do a dot notation like object.count to access the number vs the object that way you will have the desired affect. Hopefully that is what you were asking.
I would use a helper function groupBy (this version is modeled after the API from Ramda [disclaimer: I'm one of its authors], but it's short enough to just include here.) This takes a function that maps an object by to a key value, and then groups your elements into an object with those keys pointing to arrays of your original element.
We need to use that twice, once to group by month and then inside the results to group by day. The rest of the transform function is just to format your output the way I think you want.
const groupBy = (fn) => (xs) =>
xs .reduce((a, x) => ({... a, [fn(x)]: [... (a [fn (x)] || []), x]}), {})
const transform = (data) =>
Object .entries (groupBy (({date}) => date.slice(3)) (data)) // group by month
.map (([date, data]) => ({
date,
symtom: {
data: Object .entries (groupBy (({date}) => date) (data)) // group by day
.map (([date, data]) => ({
date,
data: data .map (({date, ...rest}) => ({...rest})) // remove date property
}))
}
}))
const data = [{date: "16/04/2020", count: 0, name: "A"}, {date: "16/04/2020", count: 1, name: "B"}, {date: "17/04/2020", count: 0, name: "B"}, {date: "03/05/2020", count: 0, name: "C"}];
console .log (
transform (data)
)
.as-console-wrapper {min-height: 100% !important; top: 0}
If you need to run in an environment without Object.entries, it's easy enough to shim.
You could take a function for each nested group and reduce the array and the grouping levels.
var data = [{ date: "16/04/2020", count: 0, name: "A" }, { date: "16/04/2020", count: 1, name: "B" }, { date: "17/04/2020", count: 0, name: "B" }],
groups = [
(o, p) => {
var date = o.date.slice(3),
temp = p.find(q => q.date === date);
if (!temp) p.push(temp = { date, symptom: { data: [] } });
return temp.symptom.data;
},
({ date }, p) => {
var temp = p.find(q => q.date === date);
if (!temp) p.push(temp = { date, data: [] });
return temp.data;
},
({ date, ...o }, p) => p.push(o)
],
result = data.reduce((r, o) => {
groups.reduce((p, fn) => fn(o, p), r);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Creating a SUM of nested object values in JavaScript

I'm using the following code to query an API, which is working well to return nested values in JSON:
const obj = response.data.map(function(item) {
return [item.id, item.jobNumber];
});
Example JSON:
{
"data": [
{
"id": 100,
"jobNumber": 1,
"jobTasks": [
{
"id": 12,
"cost": {
"amountString": 100
},
{
"id": 13,
"cost": {
"amountString": 500
}
}
}
]
},
{
"id": 101,
"jobNumber": 2,
"jobTasks": [
{
"id": 14,
"cost": {
"amountString": 100
},
{
"id": 15,
"cost": {
"amountString": 200
}
}
}]
}]
}
I'm wanting to now loop through the nested Job Tasks, and SUM the item.jobTasks.cost.amountString for each job, So that the following could be returned:
JobNumber1: Task Costs: 600
JobNumber2: Task Costs: 300
You can use reduce method which accepts a callback method.
Also, use forEach method in order to iterate data items.
var json={
"data": [
{
"id": 100,
"jobNumber": 1,
"jobTasks": [
{
"id": 12,
"cost": {
"amountString": 100
}
},
{
"id": 13,
"cost": {
"amountString": 500
}
}
]
},
{
"id": 101,
"jobNumber": 2,
"jobTasks": [
{
"id": 14,
"cost": {
"amountString": 100
}
},
{
"id": 15,
"cost": {
"amountString": 200
}
}
]
}]
}
json.data.forEach(function(item){
var sum=item.jobTasks.reduce(function(sum,elem){
return sum+elem.cost.amountString;
},0);
console.log('jobNumber'+item.jobNumber+' '+sum);
});
You can do it using Array#map() to create a new array and Array#reduce() to sum the amountString
const apiJson = {"data":[{"id":100,"jobNumber":1,"jobTasks":[{"id":12,"cost":{"amountString":100}},{"id":13,"cost":{"amountString":500}}]},{"id":101,"jobNumber":2,"jobTasks":[{"id":14,"cost":{"amountString":100}},{"id":15,"cost":{"amountString":200}}]}]};
const output = apiJson.data.map(d=>({
jobNumber : d.jobNumber,
tasksCost : d.jobTasks.reduce((a,b)=>a.cost.amountString+b.cost.amountString)
}));
console.log(output);
first Update your json , "}" is missing from jobTasks of second object of array data :
"jobTasks": [ { "id": 14,
"cost": {
"amountString": 100
}
},
{
"id": 15,
"cost": {
"amountString": 200
}
}
]
Now To get Output:
i = 0,1
item.jobTasks[i]cost.amountString;
Here is a solution using object-scan. We use it for most of our data processing now. It does take a moment to wrap your head around though as it is versatile.
// const objectScan = require('object-scan');
const getCounts = (data) => objectScan(['data[*].jobTasks[*].cost.amountString'], {
filterFn: ({ parents, value, context }) => {
const jobNumber = parents[3].jobNumber;
context[jobNumber] = (context[jobNumber] || 0) + value;
}
})(data, {});
const apiJson = { data: [{ id: 100, jobNumber: 1, jobTasks: [{ id: 12, cost: { amountString: 100 } }, { id: 13, cost: { amountString: 500 } }] }, { id: 101, jobNumber: 2, jobTasks: [{ id: 14, cost: { amountString: 100 } }, { id: 15, cost: { amountString: 200 } }] }] };
console.log(getCounts(apiJson));
// => { '1': 600, '2': 300 }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan

Categories

Resources