why am i getting <1 empty item> when using mapping in JavaScript - javascript

im using JSON to return an array.
Json:
const data = [{
"week": 1,
"lost": 10,
"recovery_timespan": [{
"week": 2,
"count": 1
}, {
"week": 3,
"count": 0
}],
"netLost": 10,
"netReturned": 20
}, {
"week": 2,
"lost": 7,
"recovery_timespan": [{
"week": 3,
"count": 1
}, {
"week": 4,
"count": 3
}],
"netLost": 30,
"netReturned": 200
}, {
"week": 3,
"lost": 8,
"recovery_timespan": [{
"week": 4,
"count": 1
}],
"netLost": 50,
"netReturned": 40
}];
i need to get the data into a array with lost,counts of recovery_timespan,netLost,netReturned.
Expected Output:
[ [ 10, 1, 0, 10, 20 ],
[ 7, 1, 3, 30, 200 ],
[ 8, 1, 50, 40 ] ]
My approach:
const result = data.map(({lost, recovery_timespan,netLost,netReturned}) => [
lost,
...recovery_timespan.map(({count}) => count),
,netLost,netReturned
]);
console.log(result);
and this return array with <1 empty item>:
[ [ 10, 1, 0, <1 empty item>, 10, 20 ],
[ 7, 1, 3, <1 empty item>, 30, 200 ],
[ 8, 1, <1 empty item>, 50, 40 ] ]
Wha is the issue here?

Why am i getting <1 empty item>
You have an extra comma:
const result = data.map(({lost, recovery_timespan,netLost,netReturned}) => [
lost,
...recovery_timespan.map(({count}) => count),
here ---> ,netLost,netReturned
]);
Just remove it.

You have an additional , after the nested map:
const result = data.map(({lost, recovery_timespan,netLost,netReturned}) => [
lost,
...recovery_timespan.map(({count}) => count), // <--
,netLost,netReturned
//^--
]);
That creates a hole in the array. That's why you are seeing <1 empty item> in the output
console.log([1,,2])

const res = data.map((el) => [
el.lost,
...el.recovery_timespan.map((timespan) => timespan.count),
/* extra comma here --> */, el.netLost,
el.netReturned
])
[ [ 10, 1, 0, 10, 20 ], [ 7, 1, 3, 30, 200 ], [ 8, 1, 50, 40 ] ]

Not completly sure, but maybe try this.
...recovery_timespan.map(({count}) => count.count)

Related

Javascript creates new arrays based on conditions

I have old and entity arrays:
var old = [
{
"id": 3,
"entity_type_id": 1,
"product_id": 4,
"name": "test1",
"acreage": 100,
"yield": 20,
"worth": 30
},
{
"id": 4,
"entity_type_id": 1,
"product_id": 4,
"name": "test2",
"acreage": 10,
"yield": 20,
"worth": 0
},
{
"id": 5,
"entity_type_id": 3,
"product_id": 5,
"name": "test3",
"acreage": 20,
"yield": 20,
"worth": 40
}
]
var entity = [
{"id": 1, "name": "a1"},
{"id": 2, "name": "a2"},
{"id": 3, "name": "a3"}
]
I hope to get the following data:
var newArr = [
{
"id": 3,
"entity_type_id": 1,
"product_id": 4,
"name": "test1",
"acreage": 110,
"yield": 40,
"worth": 30,
"entity_type_1": 2, // The total amount of entity_type_id (entity_type_id: 1)
"entity_type_2": 0,
"entity_type_3": 0
},
{
"id": 5,
"entity_type_id": 3,
"product_id": 5,
"name": "test3",
"acreage": 20,
"yield": 20,
"worth": 40,
"entity_type_1": 0,
"entity_type_2": 0,
"entity_type_3": 1 // The total amount of entity_type_id (entity_type_id: 3)
}
]
console.log(newArr)
I tried the following code and got some data. I'm not sure if there will be any exceptions or errors.
What's more, I don't know how to deal with the entity array data. Can someone help me solve this problem and get the result I expect?
Thank you very much !
function mergeArr(arr) {
const temp = []
arr.forEach((dataItem) => {
if (temp.length) {
let filterValue = temp.filter((items) => {
return items.product_id === dataItem.product_id
})
if (filterValue.length) {
temp.forEach((n) => {
if (n.product_id === filterValue[0].product_id) {
n.yield = dataItem.yield + filterValue[0].yield
n.acreage = dataItem.acreage + filterValue[0].acreage
n.worth = dataItem.worth + filterValue[0].worth
}
})
} else {
temp.push(dataItem)
}
} else {
temp.push(dataItem)
}
})
return temp
}
Youi could find the object and sum the wanted properties. For entity take another loop and map new entries and build a new object from it for spreading.
var old = [{ id: 3, entity_type_id: 1, product_id: 4, name: "test1", acreage: 100, yield: 20, worth: 30 }, { id: 4, entity_type_id: 1, product_id: 4, name: "test2", acreage: 10, yield: 20, worth: 0 }, { id: 5, entity_type_id: 3, product_id: 5, name: "test3", acreage: 20, yield: 20, worth: 40 }],
entity = [{ id: 1, name: "a1" }, { id: 2, name: "a2" }, { id: 3, name: "a3" }],
entityTypes = Object.fromEntries(entity.map(({ id }) => ['entity_type_' + id, 0])),
result = old.reduce((r, o) => {
let temp = r.find(q => q.product_id === o.product_id);
if (!temp) r.push(temp = { ... o, ...entityTypes });
else ['acreage', 'yield', 'worth'].forEach(k => temp[k] += o[k]);
temp['entity_type_' + o.entity_type_id]++;
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Replacing two property values in array object and creating new array

***EDIT I should have been provided a more clear question and provided better data.
I need to take an existing array of objects, replace the names depending on two different id's, and create a new array out of them.
My JSON:
const legendData = [{
"assetManagerId": 11,
"name": "AIM Derivatives",
"fileTypeId": 1,
{
"assetManagerId": 11,
"name": "AIM Derivatives",
"fileTypeId": 2,
},
{
"assetManagerId": 8,
"name": "Barings",
"fileTypeId": 2,
},
{
"assetManagerId": 5,
"name": "BlackRock",
"fileTypeId": 1,
}]
I need the AIM Derivatives names to change to the below, however, keep the rest the same.
const = legendData[{
"assetManagerId": 11,
"name": "AIM Derivatives ODIN",
"fileTypeId": 1,
{
"assetManagerId": 11,
"name": "AIM Derivatives CMF",
"fileTypeId": 2,
},
{
"assetManagerId": 8,
"name": "Barings",
"fileTypeId": 2,
},
{
"assetManagerId": 5,
"name": "BlackRock",
"fileTypeId": 1,
}]
I got halfway with my code below, however, don't know how to combine both. The below only changes if the fileTypeId is 1 but not 2.
const newArr = legendData.map(item => item.assetManagerId === 11 && item.fileTypeId === 1? {
...item, name: "AIM Derivatives ODIN"
} : item)
console.log(newArr)
You can create a dictionary and store the fileTypeId and relevant text
const legendData = [{
"assetManagerId": 11,
"name": "AIM Derivatives",
"fileTypeId": 1,
},
{
"assetManagerId": 11,
"name": "AIM Derivatives",
"fileTypeId": 2,
}
]
const idMap = {
1: "AIM Derivatives ODIN",
2: "AIM Derivatives CMF"
}
// check if the assetManagerId matches and if the `fileTypeId` is one of the key in dictionary
const newArr = legendData.map(item => item.assetManagerId === 11 && idMap[item.fileTypeId] ? {
...item,
// if one of the key the get the relevant value of that key
name: idMap[item.fileTypeId]
} : item)
console.log(newArr)
You could to try with a json config that keys are assetManagerId and fileTypeId and values are the new name.
const newNamesConfig = {
11: {
1: { name: 'AIM Derivatives ODIN' },
2: { name: 'AIM Derivatives CMF' },
},
}
const derivatesNames = [{
"assetManagerId": 11,
"name": "AIM Derivatives",
"fileTypeId": 1,
},
{
"assetManagerId": 11,
"name": "AIM Derivatives",
"fileTypeId": 2,
}];
const renamedArray = derivatesNames.map(derivate => Object.assign({}, derivate,newNamesConfig[derivate.assetManagerId][derivate.fileTypeId]));
console.log(renamedArray)
You can use map. While you will map, you can get desired name by fileTypeId from object which contains desired name:
let arr = [{
"assetManagerId": 11,
"name": "AIM Derivatives",
"fileTypeId": 1,
},
{
"assetManagerId": 11,
"name": "AIM Derivatives",
"fileTypeId": 2,
}]
const names = {1: 'AIM Derivatives ODIN', 2:'AIM Derivatives CMF'}
const result = arr.map(({name, fileTypeId, ...rest}) =>
({name: names[fileTypeId], fileTypeId, ...rest}))
console.log(result)
UPDATE:
let arr = [{ "assetManagerId": 11, "name": "AIM Derivatives", "fileTypeId": 1},{
"assetManagerId": 11, "name": "AIM Derivatives", "fileTypeId": 2,
},
{
"assetManagerId": 8, "name": "Barings", "fileTypeId": 2,
},
{
"assetManagerId": 5, "name": "BlackRock", "fileTypeId": 1,
}]
const names = {'AIM Derivatives': { 1: 'AIM Derivatives ODIN', 2:'AIM Derivatives CMF'}}
const result = arr.map(({name, fileTypeId, ...rest}) =>
({
name: names[name] ? names[name][fileTypeId] : name,
fileTypeId,
...rest
}))
console.log(result)

How to group array data in object with count using lodash

How can I groupby data with count using lodash javascript
"data": [
{
"id": 27,
"getOrderDetail": [
{
"id": 49,
"order_id": 27,
"product_id": 1,
"product_detail":[...some data...]
},
{
"id": 51,
"order_id": 27,
"product_id": 2,
"product_detail":[...some data...]
}
{
"id": 52,
"order_id": 27,
"product_id": 1,
"product_detail":[...some data...]
}
],
"getOrderStatus": []
},
]
I want to group by product_id in getOrderDetail and count it into qty for example
"data": [
{
"id": 27,
"getOrderDetail": [
{
"id": 49,
"qty": 2,
"order_id": 27,
"product_id": 1,
"product_detail":[...some data...]
},
{
"id": 51,
"order_id": 27,
"qty": 1,
"product_id": 2,
"product_detail":[...some data...]
}
],
"getOrderStatus": []
},
]
I want to do something like this
_.countBy(data, 'getOrderDetail.product_id'); and put data count into qty field
Here is what I try
let result = _.map(totalData, function(totalData, key) {
let mapData = _.groupBy(totalData.getOrderDetail, function({ product_id }) {
return product_id;
});
});
I console.log (mapData) output look like this
{
'1': [
{
id: 49,
product_id: 1,
}
],
'2': [
{
id: 51,
product_id: 2,
}
]
}
still find looking into how can I can conunt qty
You can use _.groupBy() and then map the results, and get the qty by applying _.size() to the group, and get getOrderDetail by merging the group members, concating the arrays, and spreading back to the object:
const data = [{"id":27,"getOrderDetail":[{"id":49,"order_id":27,"product_id":1,"product_detail":[]},{"id":51,"order_id":27,"product_id":2,"product_detail":[]},{"id":52,"order_id":27,"product_id":1,"product_detail":[]}],"getOrderStatus":[]}];
const result = data.map(o => ({
...o,
getOrderDetail: _.map(
_.groupBy(o.getOrderDetail, 'product_id'),
group => ({
qty: _.size(groups),
..._.mergeWith({}, ...groups, (ov, sv) =>
_.isArray(ov) ? ov.concat(sv) : sv
)
})
)
}));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Sorting array from Firebase fails

I'm trying to get an array of users sorted by the number of their likes. I am getting the user from a Firebase database, in case this changes things.
User example:
{
"likes": [
{
"createDate": {
"date": 22,
"day": 3,
"hours": 10,
"minutes": 33,
"month": 7,
"seconds": 25,
"time": 1534934005660,
"timezoneOffset": 0,
"year": 118
},
"creatorID": "1OA4U39rsPPXZblWG6nLHObB7gz1",
"firebaseKey": "-LKWBYQFbaO1Fs8_Rllc",
"workID": "-LK6-jxPZ0tCNW6c-GTI",
"id": "0"
},
{
"createDate": {
"date": 22,
"day": 3,
"hours": 13,
"minutes": 45,
"month": 7,
"seconds": 50,
"time": 1534938350990,
"timezoneOffset": -120,
"year": 118
},
"creatorID": "8Z7dd5L01FW0EbV0Wvu1KaXfmOx1",
"firebaseKey": "-LKWS7ZsUu2Khn0j7vLk",
"workID": "-LK5xZaui7IIcJcT22Rp",
"id": "1"
}
],
}
I was trying to use the sort method like this, but no luck.
var solversByLikes = solvers.sort((a, b) => a.likes.length - b.likes.length);
I am testing it by then console logging the solversByLikes array. This is the result:
0 LikesComponent.js:46
0 LikesComponent.js:46
0 LikesComponent.js:46
0 LikesComponent.js:46
2 LikesComponent.js:46
2 LikesComponent.js:46
But if I switch the a, and b, so that the sorting should be reversed, nothing changes.
var solversByLikes = solvers.sort((a, b) => b.likes.length - a.likes.length);
I tried replicating the issue like this:
allUsers = [{likes: [1, 2, 3, 4, 5, 6, 7, 8]}, {likes: [1, 2,]}, {likes: [1, 2, 3, 4, 5, 6,]}, {likes: [1, 2, 3, 4, 5,]}, {likes: [1, 2, 3, 4,]}, {likes: [1, 2, 3]}]
solversByLikes = allUsers.sort((a, b) => b.likes.length - a.likes.length);
solversByLikes.forEach(user => console.log(user.likes.length));
But this works as intended...
Any idea how to make it sort?
I'm not getting any error or anything.

Javascript 3D convex-hull algorithm similar to Matlab's convhulln

I've been struggling to find a convex-hull library for Javascript that gives the same output as the Matlab convhulln function.
I am transcribing some code from Matlab to Javascript and I need to find triangles that make up the convex hull of a set of vertices. Matlab calculates the convex hull of some 3D points using convhulln (which makes use of the qhull function). In this case Matlab convhulln outputs a different set of triangle faces to that of quickhull3d when I pass the same vertices to each. Some faces coincide but in general most do not. The only similarity they have is they both output the same number of faces (although the actual vertices of the faces are not the same).
http://www.mathworks.com/help/matlab/ref/convhulln.html
In Javascript, I've tried different libraries and each one gives a different output..
From npm I've tried:
quickhull3d - https://github.com/maurizzzio/quickhull3d
convex-hull
delaunay-triangulate
most other algorithms have been designed for 2D points, so I have ruled them out.
Any thoughts, tips or feedback would be greatly appreciated! Thank you!
Here are the vertices I'm using and the results of both MATlab's convhulln and quickhull3d. Please note I've used a sorting algorithm to sort them in the from first vertices to last. This should not effect the actual triangle faces since I sorted them in exactly the same way in both the MATlab and JS code.
Here are plots of the two hulls.
Notice the holes. I have spoken to the developer of the quickhull3d algorithm (thanks for your response!!) and he has suggested it might be that the triangulation process he used is different to one matlab uses.
vertices = [
[ 0.9510565162951535, -0.3090169943749474, 0 ],
[ 0.5877852522924731, -0.8090169943749475, 0 ],
[ 6.123233995736766e-17, -1, 0 ],
[ -0.5591929034707466, 0.8290375725550418, 0 ],
[ -0.9510565162951535, -0.3090169943749475, 0 ],
[ -0.9510565162951536, 0.3090169943749473, 0 ],
[ -0.5877852522924732, 0.8090169943749473, 0 ],
[ -1.8369701987210297e-16, 1, 0 ],
[ 0.5877852522924729, 0.8090169943749476, 0 ],
[ 0.9510565162951535, 0.3090169943749476, 0 ],
[ 0.984807753012208, 0, -0.17364817766693033 ],
[ 0.30432233187297814, -0.9366078308002486, -0.17364817766693033 ],
[ -0.796726208379082, -0.5788554735638644, -0.17364817766693033 ],
[ -0.7967262083790821, 0.5788554735638641, -0.17364817766693033 ],
[ 0.3043223318729779, 0.9366078308002487, -0.17364817766693033 ],
[ 0.5000000000000001, -0.5, 0.7071067811865475 ],
[ -0.5, -0.5000000000000001, 0.7071067811865475 ],
[ -0.5000000000000001, 0.5, 0.7071067811865475 ],
[ 0.4999999999999999, 0.5000000000000001, 0.7071067811865475 ],
[ 6.123233995736766e-17, 0, 1 ]
]
triangles from quickhull3d:
dim = 36x3
trianglesqh = [
[ 0, 1, 11 ],
[ 0, 9, 18 ],
[ 0, 10, 9 ],
[ 0, 11, 10 ],
[ 0, 15, 1 ],
[ 0, 18, 15 ],
[ 1, 2, 11 ],
[ 1, 15, 2 ],
[ 2, 12, 11 ],
[ 2, 15, 16 ],
[ 2, 16, 12 ],
[ 3, 6, 17 ],
[ 3, 7, 14 ],
[ 3, 13, 6 ],
[ 3, 14, 13 ],
[ 3, 17, 7 ],
[ 4, 5, 13 ],
[ 4, 12, 16 ],
[ 4, 13, 12 ],
[ 4, 16, 17 ],
[ 4, 17, 5 ],
[ 5, 6, 13 ],
[ 5, 17, 6 ],
[ 7, 8, 14 ],
[ 7, 17, 18 ],
[ 7, 18, 8 ],
[ 8, 9, 10 ],
[ 8, 10, 14 ],
[ 8, 18, 9 ],
[ 10, 11, 12 ],
[ 10, 12, 14 ],
[ 12, 13, 14 ],
[ 15, 18, 19 ],
[ 15, 19, 16 ],
[ 16, 19, 17 ],
[ 17, 19, 18 ]
]
triangles from MATlab:
dim = 36x3
trianglesm = [
[ 0, 1, 11 ],
[ 0, 9, 18 ],
[ 0, 10, 9 ],
[ 0, 11, 10 ],
[ 0, 15, 1 ],
[ 0, 18, 15 ],
[ 1, 2, 11 ],
[ 1, 18, 2 ],
[ 2, 3, 11 ],
[ 2, 15, 16 ],
[ 2, 16, 3 ],
[ 3, 4, 12 ],
[ 3, 12, 11 ],
[ 3, 16, 4 ],
[ 4, 5, 12 ],
[ 4, 17, 5 ],
[ 5, 8, 13 ],
[ 5, 13, 12 ],
[ 5, 16, 17 ],
[ 5, 17, 6 ],
[ 6, 7, 14 ],
[ 6, 14, 13 ],
[ 6, 17, 7 ],
[ 7, 8, 14 ],
[ 7, 17, 18 ],
[ 7, 18, 8 ],
[ 8, 9, 10 ],
[ 8, 10, 14 ],
[ 8, 18, 9 ],
[ 10, 11, 14 ],
[ 11, 12, 13 ],
[ 11, 13, 14 ],
[ 15, 18, 19 ],
[ 15, 19, 16 ],
[ 16, 19, 17 ],
[ 17, 19, 18 ]
]
You could try the Bowyer-Watson algorithm but with circumsphere and tetrahedrons:https://en.m.wikipedia.org/wiki/Bowyer%E2%80%93Watson_algorithm.

Categories

Resources