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
Let's say I have an array of objects:
Objects = [
{ "id": 1, "name": Joseph, function: "preacher"},
{ "id": 2, "name": Ann, function: "singer"},
{ "id": 3, "name": Miles, function: "preacher"},
{ "id": 4, "name": Jack, function: "singer"},
{ "id": 5, "name": Igor, function: "secretary"}
];
And also an array of properties:
sort = ['function', 'name'];
I have to sort the Objects array, using a combination of properties(sort array).
So I did it like this:
const intlCollator = new Intl.Collator('pt-BR', { usage: 'sort' });
Objects.sort(
(x, y) =>
(intlCollator.compare(x[sort[0]], y[sort[0]])) ||
(intlCollator.compare(x[sort[1]], y[sort[1]])) ||
(intlCollator.compare(x[sort[2]], y[sort[2]]))
);
How would I make the sorting dynamic?
I mean, iterate using variable sort combinations.
For example:
sort = ['function', 'name'];
Or:
sort = ['name'];
You could iterate the keys until a comparing returns a not falsy value.
const
objects = [{ id: 1, name: "Joseph", function: "preacher" }, { id: 2, name: "Ann", function: "singer" }, { id: 3, name: "Miles", function: "preacher" }, { id: 4, name: "Jack", function: "singer" }, { id: 5, name: "Igor", function: "secretary" }],
intlCollator = new Intl.Collator('pt-BR', { usage: 'sort' }),
sort = ['function', 'name'];
objects.sort((a, b) => {
let r;
sort.some(k => r = intlCollator.compare(a[k], b[k]));
return r;
});
console.log(objects);
Since ES10 sort is stable. That means you can first sort using the first key, then sort the second and so on.
const Objects = [
{ "id": 1, "name": "Joseph", function: "preacher"},
{ "id": 2, "name": "Ann", function: "singer"},
{ "id": 3, "name": "Miles", function: "preacher"},
{ "id": 4, "name": "Jack", function: "singer"},
{ "id": 5, "name": "Igor", function: "secretary"}
];
const sort = ['name', 'function'];
const intlCollator = new Intl.Collator('pt-BR', { usage: 'sort' });
sort.forEach(s => {
Objects.sort((l, r) => intlCollator.compare(l[s], r[s]));
});
console.log(Objects);
I have Array of object data which i want to sort objects of the Array by the specific key that is default. In the Array of routes. it has some object of the route. I just want to sort according to the default key. if the key default:true inside object then this object will go to the top and if default:true is found in the more than one object,then always set top of first object which found the default:true key. Also if we found the key default:true in the subarr:[] of the object then the it's parent object and this object will go to top. so, please suggest the solution for this.
Input Data:
[
{
"id": 1,
"title": 'Dashboard',
"subrr": [
{
"id": 2,
"title": 'Test'
]
},
{
"id": 3,
"title": 'Card',
"default": true,
"subrr": [
{
"id": 4,
"title": 'notification'
}
],
},
{
"id": 5,
"title": 'User',
"subrr": [
{
"id": 6,
"title": 'sample'
},
{
"id": 7,
"title": 'chart',
"default": true
}
]
},
];
/**************/
Output Data:
[
{
"id": 5,
"title": 'User',
"subrr": [
,
{
"id": 7,
"title": 'chart',
"default": true
},
{
"id": 6,
"title": 'sample'
}
]
},
,
{
"id": 3,
"title": 'Card',
"default": true,
"subrr": [
{
"id": 4,
"title": 'notification'
}
],
},
{
"id": 1,
"title": 'Dashboard',
"subrr": [
{
"id": 2,
"title": 'Test'
]
}
];
How I interpreted your sorting requirements:
Sort by element.subarr[i].default property
Sort by element.default property.
Create comparator functions for each condition you want to sort by.
const byDefault = (a, b) => (a.default === b.default ? 0 : a.default ? -1 : 1);
const bySubArrDefault = (a, b) => {
const resA = a.subarr.some((el) => el.default);
const resB = b.subarr.some((el) => el.default);
if (resA === resB) return 0;
return resA && !resB ? -1 : 1;
};
Now to sort by multiple conditions you will essentially be sorting and grouping, each group being sorted, each sub-group then sorted. The grouping/sorting is achieved by combining all the comparator functions with a logical OR (||). This logic tries to find and return the first non-zero comparator function result.
data.sort((a, b) => bySubArrDefault(a, b) || byDefault(a, b))
This sorts all data elements by the sub array element default properties, and then within that group sorts by the root default property.
const data = [
{
id: 1,
title: "Dashboard",
subarr: [
{
id: 2,
title: "Test"
}
]
},
{
id: 3,
title: "Card",
default: true,
subarr: [
{
id: 4,
title: "notification"
}
]
},
{
id: 5,
title: "User",
subarr: [
{
id: 6,
title: "sample"
},
{
id: 7,
title: "chart",
default: true
}
]
}
];
const byDefault = (a, b) => (a.default === b.default ? 0 : a.default ? -1 : 1);
const bySubArrDefault = (a, b) => {
const resA = a.subarr.some((el) => el.default);
const resB = b.subarr.some((el) => el.default);
if (resA === resB) return 0;
return resA && !resB ? -1 : 1;
};
const sorted = data
.slice(0)
.sort((a, b) => bySubArrDefault(a, b) || byDefault(a, b));
console.log(sorted);
I want to restructure the current JSON of data as shown below
const data = [
{
"status": "Complete",
"totalToday": 3,
"weekly": 20
},
{
"status": "Pending",
"totalToday": 5,
"weekly": 13
},
{
"status": "Rejected",
"totalToday": 2,
"weekly": 5
}
];
Expected output:
const newData = [
['Status', 'Total Today', 'Weekly'],
['Complete', 3, 20],
['Pending', 5, 13],
['Rejected', 2, 5]
];
You can use Array.forEach()
const data = [{
"status": "Complete",
"totalToday": 3,
"weekly": 20
},
{
"status": "Pending",
"totalToday": 5,
"weekly": 13
},
{
"status": "Rejected",
"totalToday": 2,
"weekly": 5
}
];
let transformedData = []
transformedData.push(Object.keys(data[0]).map(key => {
return key.replace(/([A-Z])/g, ' $1')
.replace(/^./, (str) => str.toUpperCase())
}))
data.forEach(val => transformedData.push(Object.values(val)))
console.log(transformedData)
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
You can simply use a reduce method, in which you iterate over an Array of Object. On the 0 index, you can use Object.keys() to get the key and Object.values for the corresponding values and push it to the accumulator. For else you can iterate Object values and push it to the accumulator acc.
const data = [
{
"status": "Complete",
"totalToday": 3,
"weekly": 20
},
{
"status": "Pending",
"totalToday": 5,
"weekly": 13
},
{
"status": "Rejected",
"totalToday": 2,
"weekly": 5
}
];
const newData = data.reduce((acc, x, idx) => {
if(idx === 0) {
acc.push(Object.keys(x), Object.values(x));
} else {
acc.push(Object.values(x));
}
return acc;
}, [])
console.log(newData);
array1 = [{
"id": 1,
"name": "aaa",
},
{
"id": 2,
"name": "bbb"
},
{
"id": 5,
"name": "ccc"
},
{
"id": 6,
"name": "ddd"
},
{
"id": 8,
"name": "eee"
},
{
"id": 12,
"name": "fff"
}]
array2 = [ 5, 6, 8 ,12]
Resulting Array = [ {name: "ccc"}, {name: "ddd"} , {name: "eee"}, {name: "fff"} ]
I am looking to map both arrays to get matching id numbers and get copy the names in the resulting arrray but I didn't succeed. Can you please suggest me how to do it?
Thank you
You could try the following. Basically, you're filtering the first array based on whether or not the id exists in the 2nd array and then mapping it back by only selecting the key(s) you want.
var resultArray = array1.filter(function(arr) {
return array2.indexOf(arr.id) !== -1;
}).map(function(item) {
return {
name: item.name
};
});
Let's turn array1 into an object first, that maps ids to the corresponding objects:
var idMap = {}
array1.forEach(function(element) {
idMap[element.id] = element
})
You can then get the result you want by doing
var result = array2.map(function(id) {
return idMap[id]
});
Try This:
array1 = [{"id": 1,"name": "aaa"},{"id": 2,"name": "bbb"},{"id": 5,"name": "ccc"},{"id": 6,"name": "ddd"},{"id": 8,"name": "eee"},{"id": 12,"name": "fff"}] ;
array2 = [ 5, 6, 8 ,12];
var result = array1.filter(item => array2.includes(item.id)).map(({id,name}) => ({name}));
console.log( result );
How can we retrieve name from the json, when array of ids are provided.
[
{
"id": 0,
"name": "salesTransNo"
},
{
"id": 1,
"name": "terminalNo"
},
{
"id": 2,
"name": "salesTransDate"
},
{
"id": 3,
"name": "salesTransTime"
},
{
"id": 4,
"name": "exceptionAmount"
},
{
"id": 5,
"name": "laneNumber"
}
]
I want to retrieve only names into an array from the JSON, when array of id values are given
eg: array of id's : [2,4,5]
Output should be:
["salesTransDate","exceptionAmount","LaneNumber"]
How can we achieve this with Lodash or with JavaScript ?
I used _.find and used _.map to pull only name from the result, but it's only working for single value, if I were to pass an array like [2,4,5] it's not working.
You could filter the objects and then map the wanted property.
var data = [{ id: 0, name: "salesTransNo" }, { id: 1, name: "terminalNo" }, { id: 2, name: "salesTransDate" }, { id: 3, name: "salesTransTime" }, { id: 4, name: "exceptionAmount" }, { id: 5, name: "laneNumber" }],
ids = [2, 4, 5],
result = data
.filter(({ id }) => ids.includes(id))
.map(({ name }) => name);
console.log(result);
Vanilla JS:
var arr = [
{ "id": 0, "name": "salesTransNo" },
{ "id": 1, "name": "terminalNo" },
{ "id": 2, "name": "salesTransDate" },
{ "id": 3, "name": "salesTransTime" },
{ "id": 4, "name": "exceptionAmount" },
{ "id": 5, "name": "laneNumber" }
];
var indexes = arr.map ( function ( d ) { return d.id; });
var id = 4; // Requested arr.id item
var select_name = arr[indexes.indexOf(id)].name;
If you wish to return multiple results, you can build a function like so:
function getNamesFromArr ( list_of_ids ) {
var result = [];
for ( var i = 0; i < list_of_ids.length; i++ ) {
var indexes = arr.map ( function ( d ) { return d.id; });
var select_name = arr[indexes.indexOf(list_of_ids[i])].name;
result.push ( select_name );
}
return result;
}
getNamesFromArr ([ 2, 4, 5 ]); // Returns ["salesTransDate", "exceptionAmount", "laneNumber"]
Note: I had left out error handling for simplicity. Consider catching indexOf() values of -1.
var items = [{
"id": 0,
"name": "salesTransNo"
},
{
"id": 1,
"name": "terminalNo"
},
{
"id": 2,
"name": "salesTransDate"
},
{
"id": 3,
"name": "salesTransTime"
},
{
"id": 4,
"name": "exceptionAmount"
},
{
"id": 5,
"name": "laneNumber"
}
]
var iname = items.filter(items => [2, 4, 5].includes(items.id));
for (var names of iname)
{console.log(names.name);}
You can do that with a lodash's chain using _.keyBy(), _.at(), and _.map():
var data = [{ id: 0, name: "salesTransNo" }, { id: 1, name: "terminalNo" }, { id: 2, name: "salesTransDate" }, { id: 3, name: "salesTransTime" }, { id: 4, name: "exceptionAmount" }, { id: 5, name: "laneNumber" }];
var ids = [2, 4, 5];
var result = _(data)
.keyBy('id') // convert to a dictionary by id
.at(ids) // get the items which id match the id array
.map('name') // pluck the name
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
You can use lodash#intersectionWith, wherein the arguments order must be the collection first, the ids second and the comparator at the end.
var result = _.intersectionWith(data, ids, (a, b) => a.id == b);
var data = [{
id: 0,
name: "salesTransNo"
}, {
id: 1,
name: "terminalNo"
}, {
id: 2,
name: "salesTransDate"
}, {
id: 3,
name: "salesTransTime"
}, {
id: 4,
name: "exceptionAmount"
}, {
id: 5,
name: "laneNumber"
}],
ids = [2, 4, 5];
var result = _.intersectionWith(data, ids, (a, b) => a.id == b);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>