how can i sort this tests array based on discount_price i have sorted only the lab_partners array,,,can anyone tell me how to sort the main array nd so that array should look something like : 200 ,250, 299 ,500 so my array is something like this - [ { [ ] } ,{ [ ] } , { [ ] } ,]
"tests": [
{
"id": 11,
"habit_test_id": 3,
"test_id": 1,
"test": {
"id": 1,
"test_name": "Blood Test",
},
"lab_partners": [
{
"id": 1,
"discounted_price": 250,
},
{
"id": 7,
"discounted_price": 299,
}
]
},
{
"test": {
"id": 4,
"test_name": "MRI",
},
"lab_partners": [
{
"id": 6,
"discounted_price": 500,
},
{
"id": 6,
"discounted_price": 200,
}
]
}
]
}
//this only sort the lab_partners array i want to sort on the basis of both test array
const condition_based= tests.map((itr, idx) =>
itr.lab_partners.sort((firstItem, secondItem) => ( firstItem.discounted_price -
secondItem.display_price)));
console.log(condition_based,'condition_based');
I don't really know what you are trying to achieve, or what you expect from this array, but please look into this
https://www.w3schools.com/JS/js_object_constructors.asp
It seems to me like there are some similarities in all the object values, and you are missing out some maybe just because they are null values.
Related
I have an array of subscriptions group by the type (basic,medium ...)
`
[
[
"Basic",
[
{ "id": 2, "name": "Basic", "started_at": "2022-01-24", "count": 4 },
{ "id": 2, "name": "Basic", "started_at": "2022-03-16", "count": 2 },
{ "id": 2, "name": "Basic", "started_at": "2022-05-16", "count": 1 }
]
],
[
"Medium",
[
{ "id": 3, "name": "Medium", "started_at": "2022-02-21", "count": 1 },
{ "id": 3, "name": "Medium", "started_at": "2022-05-28", "count": 1 }
]
],
[
"Premium",
[{ "id": 4, "name": "Premium", "started_at": "2022-04-21", "count": 1 }]
],
[
"Master",
[
{ "id": 7, "name": "Master", "started_at": "2022-07-28", "count": 1 },
{ "id": 7, "name": "Master", "started_at": "2022-08-02", "count": 1 }
]
],
[
"Jedi",
[{ "id": 6, "name": "Jedi", "started_at": "2022-09-28", "count": 1 }]
]
]
`
What I want to do is return an array containing objects foreach sub with the following data(get the count value by month):
`
[
{
label: "Basic",
data: [4, 0, 2, 0, 1,0],
},
{
label: "Medium",
data: [0, 1, 0, 0, 1,0],
},
...
]
`
The data field should contain the count field foreach subscription corresponding to the month. For example for with count 4 in January and count 2 in March it will return [4,0,1] with 0 for February.
How can I achieve that ?
I did this but it's returning only the existing month values so there is no way to know which month that value is for.
subscriptions.map((item) => {
return {
label: item[0],
data: item[1].map((value, index) => {
return value.count;
}),
};
})
You could reduce the array and create a mapper object which maps each plan with month specifc count. Something like this:
{
"Basic": {
"1": 4,
"3": 2,
"5": 1
},
"Medium": {
"2": 1,
"5": 1
},
...
}
Then loop through the entries of the object and create objects with plan as label and an array of length: 12 and get the data for that specific month using the index
const input=[["Basic",[{id:2,name:"Basic",started_at:"2022-01-24",count:4},{id:2,name:"Basic",started_at:"2022-03-16",count:2},{id:2,name:"Basic",started_at:"2022-05-16",count:1}]],["Medium",[{id:3,name:"Medium",started_at:"2022-02-21",count:1},{id:3,name:"Medium",started_at:"2022-05-28",count:1}]],["Premium",[{id:4,name:"Premium",started_at:"2022-04-21",count:1}]],["Master",[{id:7,name:"Master",started_at:"2022-07-28",count:1},{id:7,name:"Master",started_at:"2022-08-02",count:1}]],["Jedi",[{id:6,name:"Jedi",started_at:"2022-09-28",count:1}]]];
const mapper = input.reduce((acc, [plan, subscriptions]) => {
acc[plan] ??= {}
for(const { started_at, count } of subscriptions)
acc[plan][+started_at.slice(5,7)] = count
return acc;
}, {})
const output =
Object.entries(mapper)
.map( ([label, subData]) => ({
label,
data: Array.from({ length: 12 }, (_, i) => subData[i+1] ?? 0)
}) )
console.log(output)
Note:
This assumes that the data is for a single year only. If it can be across years you'd have to create another level of nesting:
{
"Basic": {
"2022": {
"1": 3
}
}
}
started_at.slice(5,7) is used to get the month number. If the dates are not in the ISO 8601 format, you can use new Date(started_at).getMonth() + 1 to get the month part.
I created multiple nested map function of an object array and I ended up in the kind of output.
let tags = product.map(item => item.outSourceItem.map(outsourceitem => outsourceitem.tags));
tags = [
[
[
{
"_id": 11,
"name": "eleven"
}
]
],
[
[
{
"_id": 12,
"name": "twelve"
}
]
],
[
[
{
"_id": 13,
"name": "thirteen"
}
]
],
[
[
{
"_id": 11,
"name": "eleven"
}
]
]
]
I just want it to be like this.
[
{
"_id": 11,
"name": "eleven"
},
{
"_id": 12,
"name": "twelve"
},
{
"_id": 13,
"name": "thirteen"
},
{
"_id": 11,
"name": "eleven"
}
]
any one liner function for this? I use .flat() but it doesn't work either.
Try Array#flat with depth of infinity:
const tags = [
[
[
{
"_id": 11,
"name": "eleven"
}
]
],
[
[
{
"_id": 12,
"name": "twelve"
}
]
],
[
[
{
"_id": 13,
"name": "thirteen"
}
]
],
[
[
{
"_id": 11,
"name": "eleven"
}
]
]
];
const result = tags.flat(Infinity);
console.log(result);
How do I combine 2 nested arrays.
There are 2 Array A and B
const A = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
},
{
"id": 0.1223,
"rk": false,
"title": "risk23"
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 2,
"bp": true,
"ba": "value2"
}
]
.
const B = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
},
{
"id": 0.211,
"mk": true,
"title": "obli44",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 3,
"bp": true,
"ba": "value3"
}
]
.
on combining A and B the output should be of below format.
We need to take risk from table A and we need to take master from table B and add it to table C.
The Final array looks like the following.
.
const c = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
},
{
"id": 0.1223,
"rk": false,
"title": "risk23"
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
},
{
"id": 0.211,
"mk": true,
"title": "obli44",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 2,
"bp": true,
"ba": "value2"
},
{
"id": 3,
"bp": true,
"ba": "value3"
}
]
The data can be more than 1000 records. please help me with which it will save time and complexity.
Thanks in Advance.
The first thing you need to do is to isolate the IDs from array A and B. You can also map over the two of them concatenated together, but then you may have duplicate values. This seems like a rational way to go about ensuring single entries for each ID.
const allIds = [...a.map(x => x.id), ...b.map(x => x.id)];
const uniqueIds = allIds.reduce((prev, curr) => {
return prev.includes(curr) ? prev : [...prev, curr]
}, []);
Then you need to take those uniqueIds, and map over each of them. For each ID, you need to return the matching object in A and the matching object in B, but overwrite the risk property with the value from the object in A and overwrite the master property with the value from the object in B.
That can be done by just finding the matching objects in A and B, and then use the spread operator to assign their entries to the new object.
Note: If the properties outside of risk and master (e.g. bp or ba) have different values, then the element listed last will overwrite it. In the below case, that means if the bp value in A is true and the bp value in B is false, then the bp value in C will be false.
const c = uniqueIds.map(id => {
const elementInA = a.find(x => x.id === id);
const elementInB = b.find(x => x.id === id);
return {
...elementInA,
...elementInB,
risk: [
...elementInA?.risk ?? []
],
master: [
...elementInB?.master ?? []
]
};
});
Instead of looping through multiple times both arrays, I would suggest something that will loop through each array, not more than needed.
The following approach will loop through twice the first array, and once the B array. (not considering the indexOf method).
const ids = A.map(({id}) => id), C = A.map(a => a);
for(let b of B){
let index = ids.indexOf(b.id);
if(index < 0){
C.push(b);
} else {
C[index] = {
...A[index],
...b,
risk: [
...A[index]?.risk ?? []
],
master: [
...b?.master ?? []
]
}
}
}
This question already has answers here:
How to sort an array based on the length of each element?
(12 answers)
Closed 1 year ago.
I have an array like below, and I need to sort the array by the string length of name field.
for an example,
[
{
"_id": 10,
"name": "AAAAAA"
},
{
"_id": 11,
"name": "AA"
},
{
"_id": 12,
"name": "AAAA"
},
{
"_id": 13,
"name": "A"
},
{
"_id": 14,
"name": "AAAAAAAA"
}
]
I need the array like this,
[
{
"_id": 13,
"name": "A"
},
{
"_id": 11,
"name": "AA"
},
{
"_id": 12,
"name": "AAAA"
},
{
"_id": 10,
"name": "AAAAAA"
},
{
"_id": 14,
"name": "AAAAAAAA"
}
]
can any one help me out with this. Thanks.
This can be accomplished with the _.orderBy method:
_.orderBy(data, [({ name }) => name.length, 'name'], ['desc']);
Here is a break-down:
I threw some "B"s into the mix to show the secondary sorting (after length is compared). Sorting the length alone is not unique enough.
const data = [
{ "_id": 1, "name": "AAAAAA" },
{ "_id": 2, "name": "AA" },
{ "_id": 3, "name": "AAAA" },
{ "_id": 4, "name": "A" },
{ "_id": 5, "name": "AAAAAAAA" },
{ "_id": 6, "name": "BBBBBB" },
{ "_id": 7, "name": "BB" },
{ "_id": 8, "name": "BBBB" },
{ "_id": 9, "name": "B" },
{ "_id": 10, "name": "BBBBBBBB" }
];
const sorted = _.orderBy(
data, // Data to be sorted
[
({ name: { length } }) => length, // First, sort by length
'name' // Them sort lexicographically
], [
'desc', // Length (descending)
'asc' // This is implied, and could be removed
]
);
console.log(sorted);
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
I have a collection of objects in this array and I need to order them by the 'order' key (asc). Is there a way to sort the objects inside the array and then return the whole array? I am relying on the order as I'm using it in a v-for with a :key.
[
{
"id":0,
"type":"Header",
"order":1,
"props":{
"order":0,
"id":0,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
},
{
"id":1,
"type":"Header",
"order":0,
"props":{
"order":1,
"id":1,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
}
],
[
//Another collection of objects
]
I am currently doing this -
getters: {
sorted: state => {
return _.orderBy(state.experience_sections, function(block) {
if(block.experience_blocks[0]) {
return block.experience_blocks[0].order;
}
});
}
}
The solution above does not seem to order the objects by 'asc' order. Am I on the right track?
Thanks!
P.S. Stack is telling me that is a possible duplicate question but I'm at a loss after hours of searching. My apologies if I missed an already answered question.
Just in case you want plain javascript solution.. using Array.forEach
I have also extended your array to contain more data
var arr = [[
{
"id":0,
"type":"Header",
"order":1,
"props":{
"order":0,
"id":0,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
},
{
"id":1,
"type":"Header",
"order":0,
"props":{
"order":1,
"id":1,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
}
], [
{
"id":0,
"type":"Header",
"order":2,
"props":{
"order":0,
"id":0,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
},
{
"id":1,
"type":"Header",
"order":1,
"props":{
"order":1,
"id":1,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
}
]]
arr.forEach(d => d.sort((a,b) => a.order - b.order))
console.log(arr)
You should also consider orderBy method from lodash since you could easily change from asc to desc sort order if you would want to at a later date or have it via a variable being passed through the UI etc:
const data = [ [{ "id": 0, "type": "Header", "order": 1, "props": { "order": 0, "id": 0, "section_id": 0 }, "data": { "header": "" }, "component": "header-block" }, { "id": 1, "type": "Header", "order": 0, "props": { "order": 1, "id": 1, "section_id": 0 }, "data": { "header": "" }, "component": "header-block" } ], [{ "id": 0, "type": "Header", "order": 2, "props": { "order": 0, "id": 0, "section_id": 0 }, "data": { "header": "" }, "component": "header-block" }, { "id": 1, "type": "Header", "order": 1, "props": { "order": 1, "id": 1, "section_id": 0 }, "data": { "header": "" }, "component": "header-block" } ] ]
console.log('asc:', _.map(data, x => _.orderBy(x, 'order'))) // asc order
console.log('desc:', _.map(data, x => _.orderBy(x, 'order', 'desc'))) // desc
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Will sort each subarray in an array
const sortedArr = _.map(arr, subArray => _.sortBy(subArray, "order"));
Deep sorting using lodash
const sortedArray = _.orderBy(items, [(item) => {
const nestedObj = _.get(item, 'props');
item['props'] = _.orderBy(nestedObj,'order','desc');
return item['order'];
}], 'desc');