I have an array and I need to order the data of it by the distance of a specific point.
Knowing that .sort() won't work since I'm dealing with coordinates, I've been using a library called Geolib which has a function called getPreciseLocation() which is exactly what I need, but it doesn't seem to work while iterating through an array.
Here is the array containing the data I will be using.
Data:
[
{
"id": "1",
"Point": "27.1597268, 40.6646601"
},
{
"id": "2",
"Point": "11.1640393, 49.648713"
},
{
"id": "3",
"Point": "26.1539253, 42.6599287"
},
{
"id": "4",
"Point": "21.1597268, 44.6646601"
},
{
"id": "5",
"Point": "10.1640393, 43.648713"
},
{
"id": "6",
"Point": "26.1539253, 61.6599287"
}
]
The code I've been trying to use to iterate through the array.
let DistancesFromUserLocation = [];
this.state.Data.forEach(item => {
DistancesFromUserLocation.push(geolib.getPreciseDistance({latitude: 30.1891168, longitude: 11.6226982}, item.Point))
})
As a disclaimer: I only need to get to receive the distance of each array object to a new array.
I've tried and researched many things and get around the solution, but just about thinking that I am getting to the solution, something would go wrong.
You need to push the generated distance each iteration to DistancesFromUserLocation array.
let DistancesFromUserLocation = [];
this.state.Data.forEach(item => {
// push each distance to `DistancesFromUserLocation`
DistancesFromUserLocation.push(
geolib.getPreciseDistance(
{latitude: 30.1891168, longitude: 11.6226982},
item.Point
);
)
})
Only then you can use the Array.sort().
console.log(DistancesFromUserLocation.sort());
EDIT:
Check my working example here at codesandbox.
Related
I am trying to get the total length from an array using reduce. But I encountered a problem when I saw that the length was prefixed by 'km'. So I am trying to remove(substring) the 'km', then add the length. Here's what I've done so far:
this.totalLength= this.roads.map((road) => road.distance)
.reduce((prev, next) => prev + parseFloat(next.substring(2)));
It is working but it is not adding the second value of the array to the totalLength.
Here's the sample of the array:
[
{
"Id": "1",
"distance": "Km12.20",
"name": "Hwy1"
},
{
"Id": "2",
"distance": "Km19.60",
"name": "Hwy2"
}
]
I would recommend searching for a float using regex if you think it may be prefixed or suffixed by any other text. You can use the regex /(\d*\.)?\d+/ to do so.
Additionally, <Array>.reduce takes an additional parameter for the starting value, so make sure to provide that.
this.totalLength= this.roads.map((road) => road.distance)
.reduce((prev, next) => prev + (parseFloat(next.match(/(\d*\.)?\d+/)[0])||0), 0);
What you did is almost correct. reduce also expects a second argument which is the initial value.
const roads = [
{
"Id": "1",
"distance": "Km12.20",
"name": "Hwy1"
},
{
"Id": "2",
"distance": "Km19.60",
"name": "Hwy2"
}
]
roads
.map((road) => road.distance)
.reduce((prev, next) => prev + parseFloat(next.substring(2)), 0);
I have this object:
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
and i want to add an element and have an output like this:
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"land": "111", // THIS <<<<------------
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
i tried using splice but not works...
ages.splice(ages[0]['getasafieldDetail']['asaentrySet'][0]['offerSet'],0,'"land": "111"');
ages.join();
There is the handy syntax of Destructuring assignments which helps with cutting and reassembling objects.
Edit
#FireFuro99 did point to the ES6/ES2015 spec which explicitly states how to preserve/handle an object's key-order at the object's creation time.
Thus one can say ...
Every JS engine which does support Destructuring assignment has to respect too any object's key order from/at this object's creation time.
const ages = [{
getasafieldDetail: {
id: "xxx",
asaentrySet: [{
result: "ON",
buy: {
username: "Dis",
},
offerSet: [{
createdStr: "2001-08-09 at 11:52 pm",
value: 5.0,
}],
}],
},
}];
const { result, buy, ...rest } = ages[0].getasafieldDetail.asaentrySet[0];
ages[0].getasafieldDetail.asaentrySet[0] = {
result,
buy,
land: "111",
...rest,
};
console.log({ ages });
.as-console-wrapper { min-height: 100%!important; top: 0; }
Splice only works on Arrays.
To make this work, convert your Object to an Array using Object.entries(), then use splice, and then convert it back to an object using Object.fromEntries().
const entrySet = Object.entries(ages[0]['getasafieldDetail']['asaentrySet'][0]);
entrySet.splice(2,0, ["land", "111"]);
ages[0]['getasafieldDetail']['asaentrySet'][0] = Object.fromEntries(entrySet);
This will insert the key-value pair at the the specified position.
The advantage this has over the destructuring assignment is, that you can specify the index, whereas destructuring is pretty hardcoded.
ages[0]["getasafieldDetail"]["asaentrySet"][0].land = '111' will create the key land in the first object in asaentrySet and assign the value 111. Key order is not guaranteed
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
ages[0]["getasafieldDetail"]["asaentrySet"][0].land = '111'
console.log(ages)
When it is an array of objects you could simple, add, passing the position that you want by editing the array like the example below:
let land = {land: 1111}
let ages = [{'a':11},'2', 'wd']
let new =[]
new.push(ages[1])
new.push(land)
ages[1] = new
console.log(ages)
output:
(3) [{…}, Array(2), "wd"]
You get what you want from the array, edit it, and put back in the same position, may it can help.
I've been trying to wrap my head around filtering arrays of objects for a while now, but I can't seem to really get a hang on it. Although I usually have working code in the end, it just doesn't look like elegant code to me. So, I'd appreciate a code review and some hints very much!
Example:
I'm currently working on this example for an online shop where I need to retrieve product details out of an array of objects based on an id.
This is my helper function:
function getItemDetails(id) {
var getCategory = shelf.filter(obj => obj.articleList.some(cat => cat.id === id));
var getArticleList = getCategory[0].articleList;
var getItem = getArticleList.filter(item => item.id == id);
return getItem
}
Steps: In a first step, I tried to filter the shelf array, but it would return the entire array articleList of the corresponding item.
So, I filtered the result again with the same criteria and it works, but it just looks awfully redundant to me.
This is an example of the data:
const shelf = [{
"categoryPrice": "2",
"categoryTitle": "Flyer",
"articleList": [{
"id": "1",
"articleTitle": "Green",
}, {
"id": "2",
"articleTitle": "Blue",
}],
}, {
"categoryPrice": "3",
"categoryTitle": "Post card",
"articleList": [{
"id": "3",
"articleTitle": "Purple"
}, {
"id": "4",
"articleTitle": "Yellow",
}]
}]
I checked various questions here, including:
Vue/Javascript filter in deep object inside object array
Deep filter objects in javascript array
But none of them provide an easier, more concise solution, in my opinion. What am I missing?
Thanks for your help!
This might be a better fit for codereview but if the question is just 'How to make this more concise' I would suggest something like following:
const shelf = [{
"categoryPrice": "2",
"categoryTitle": "Flyer",
"articleList": [{
"id": "1",
"articleTitle": "Green",
}, {
"id": "2",
"articleTitle": "Blue",
}],
}, {
"categoryPrice": "3",
"categoryTitle": "Post card",
"articleList": [{
"id": "3",
"articleTitle": "Purple"
}, {
"id": "4",
"articleTitle": "Yellow",
}]
}]
const findItem = function(shelves, id) {
return shelves.flatMap((shelf) => shelf.articleList).find((article) => article.id == id) || null;
}
console.log(findItem(shelf, 1));
console.log(findItem(shelf, 3));
The above example concatenate all the list of articles and then searches that array for the article with the supplied ID.
Performance wise? Not the best, but you asked for something concise and this is about as concise as one can hope for with the given data structure.
This code is O(1), which means that lookup per article.id is constant. It will however use more memory. To conserve memory, I used WeakMap, as long as you use the same shelf variable, it will not recompute it. But once you replace it, it will also perish from the cache.
const shelf = [{
"categoryPrice": "2",
"categoryTitle": "Flyer",
"articleList": [{
"id": "1",
"articleTitle": "Green",
}, {
"id": "2",
"articleTitle": "Blue",
}, {
"id": "3", // Added
"articleTitle": "Violet",
}],
}, {
"categoryPrice": "3",
"categoryTitle": "Post card",
"articleList": [{
"id": "3",
"articleTitle": "Purple"
}, {
"id": "4",
"articleTitle": "Yellow",
}],
}];
const findItems = function(shelves, id) {
if (!findItems._map) {
// Create computation cache holder
// Weak map will make sure, that if the object is disposed, it can be garbage collected, with it will be gone its cache too! (That is awsome!)
findItems._map = new WeakMap();
}
if (!findItems._map.has(shelves)) {
// For every shelves object, we will create a new Map containing all mapped values.
const map = new Map();
findItems._map.set(shelves, map);
shelves.forEach(shelf => {
shelf.articleList.forEach(article => {
if (!map.has(article.id)) {
// If list is not yet created create it with the article
return map.set(article.id, [ article ]);
}
// If it exists, add to it
map.get(article.id).push(article);
});
});
}
return findItems._map.get(shelves).get(id);
}
console.log(findItems(shelf, "1"));
console.log(findItems(shelf, "3"));
You can get away with looping twice. Once for the outer array and once for the articleList array
const findItem = (id) =>
shelf.reduce((acc, current) => {
const found = current.articleList.find((x) => x.id === id);
if (found) return [...acc, found];
return acc;
}, []);
{
"3": {
"id": "3",
"ocena_ocena": "2",
"ocena_profesor": "\u041c\u0430\u0440\u043a\u043e \u041c\u0430\u0440\u043a\u043e\u0432\u0438\u045b",
"ocena_napomena": "",
"ocena_datum": "31.12.2015."
},
"1": {
"id": "1",
"ocena_ocena": "5",
"ocena_profesor": "\u041c\u0430\u0440\u043a\u043e \u041c\u0430\u0440\u043a\u043e\u0432\u0438\u045b",
"ocena_napomena": "",
"ocena_datum": "22.12.2015."
}
}
I am using ajax to get this JSON. I tried parsing it like this:
request.done(function(response) {
alert(response.ocena_ocena);
});
Could someone please help me with this?
I also need to know how can I do a foreach statement with json?
Since your JSON represents a JavaScript object, you should include the attribute name (if we consider JavaScript object to be a map, then, we need to use the key).
Try
response["1"].ocena_ocena
or
response["3"].ocena_ocena
Since you are returning a JSON object from server instead of an array, to iterate over its properties, you could do
for (var i in response) {
console.log(response[i].ocena_ocena);
}
or
Object.keys(response).forEach(function f(e) {console.log(response[e].ocena_ocena)})
If you could modify your server side code to return JSON that looks like this,
[
{
"id": "3",
"ocena_ocena": "2",
...
},
{
"id": "1",
"ocena_ocena": "5",
...
}
]
then you could iterate over it more easily
response.forEach(function f(e) {console.log(e.ocena_ocena)})
I hava a json object have some records, and I need to sort the object,
code:
var data = [
{
"MRData": {
"StandingsTable": {
"StandingsLists": [
{
"season": "2014",
"round": "5",
"DriverStandings": [
{
"position": "2",
"positionText": "1",
"points": "100",
"wins": "4",
"Driver": {...},
"Constructors": [...]
},
{
"position": "1",
"positionText": "2",
"points": "97",
"wins": "1",
"Driver": {...},
"Constructors": [...]
}
]
}
]
}
}
}
];
//What is Wrong in This function
function sortObj(obj, nextObj){
console.log(obj.position);
console.log(nextObj.position);
if(obj.position < nextObj.position){
return obj;
}else{
return nextObj;
}
}
var driverObjects = data[0].MRData.StandingsTable.StandingsLists[0].DriverStandings;
console.log(driverObjects);
var sortedData = driverObjects.sort(sortObj); //Do I need to use any other functions //like filter, map ?
console.log(sortedData);
Fiddle
Have a look at the console, to use the output, I was excepting the output like
[Object { position="1", positionText="1", points="100", more...}, Object { position="2", positionText="2", points="97", more...}]
But it is displaying same as passed function.
please correct the function mistakes.
Give me an optimized or more standard code implementation
sortObj() should return either positive value or negative value or 0
You can do like this..
function sortObj(obj, nextObj){
console.log(obj.position);
console.log(nextObj.position);
return nextObj.position-obj.position
}
The callback function for the sort method should return -1 (when the second parameter is greater), 0 (when both parameters are equal) or 1 (when the first parameter is greater)
Array.prototype.sort()
so you need this sort function:
function sortObj(obj, nextObj){
return obj.position - nextObj.position;
}