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);
Related
I am building a Blog app and I am trying to get results but it is showing duplicate results, I am trying to remove the duplicate results from the array.
But the problem is there are two key and values in each dict inside array, One is unique and other can be same so I am trying to distinct based on same array, It worked But the other key and value pair (which is unique) is not attaching with the other pair.
response which is returning from db
[
{
"id": 2,
"name": "user_1"
},
{
"id": 3,
"name": "user_3"
},
{
"id": 4,
"name": "user_3"
}
]
App.js
function App() {
const [blogs, setBlogs] = useState([]);
axios.get("retract_blogs/").then((res) => {
// Here I also want to attach "id"
setBlogs({[...new Set(res.data.data.map(x => x.name))]})
}
return(
<div>
{
blogs.map((user) =>
<div>
{user.name}
// Here I wamt to show ID
// {user.id}
</div>
}
</div>
)
}
I want to add id with x.username, I also tried using
setBlogs({data:[...new Set(res.data.data.map(x => x.name, x.id))]})
But it showed
x is not defined
But I am trying to add both name and id, and remove duplicates based on name not id.
I have tried many times but it is still not working.
To keep the id of the last occurence you can create a Map of the array keyed by name and then convert back to an array using the iterator returned by Map.values(). This works by overwriting earlier entries in the Map with the same name.
const users = [{ "id": 2, "name": "user_1" }, { "id": 3, "name": "user_3" }, { "id": 4, "name": "user_3" }];
const result = [...new Map(users.map((user) => [user.name, user])).values()];
console.log(result);
// [ { id: 2, name: 'user_1' }, { id: 4, name: 'user_3' } ]
If you instead want to keep the id of the first occurence of a name you can use a slightly modified 'group by' grouping into an object by name (here in a reduce() call, but it could easily be done in a standard loop as well) before taking the Object.values. This works by only setting the accumulator[name] property if it doesn't already exist, here using logical nullish assignment (??=)
const users = [{ "id": 2, "name": "user_1" }, { "id": 3, "name": "user_3" }, { "id": 4, "name": "user_3" }];
const result = Object.values(users.reduce((a, c) => (a[c.name] ??= c, a), {}));
console.log(result);
// [ { id: 2, name: 'user_1' }, { id: 3, name: 'user_3' } ]
My question title may not be the accurate way to describe this issue but it is the best I could come up with. I will make this very easy -- I am trying to get the value of VALUEIWANT from the below JSON object.
Any help would be greatly appreciated as I have been trying various methods on w3 schools for 2 hours now.
The closest I have gotten by hard coding was below:
const x =
{ "UserAttributes":
[ { "Name" : "sub"
, "Value": "54f5cdfb-6ec7-4683-fdasfasdf-2324234234"
}
, { "Name" : "custom:var"
, "Value": "VALUEIWANT"
}
, { "Name" : "email"
, "Value": "test.user#email.com"
}
]
, "Username": "testuser"
}
const y = x.UserAttributes[1].Value
// y here would result in VALUEIWANT
The problem with this is I am not sure that the variable will always be at index 1.
EDIT For Clarity My goal is to be able to retrieve this value of "VALUEIWANT" in my console. I need to be able to access the value by using the paired Name of "custom:var". I am unsure if this is possible.
The problem with this is I am not sure that the variable will always
be at index 1.
You need to find the index using findIndex (MDN)
const x = {
"UserAttributes": [{
"Name": "sub",
"Value": "54f5cdfb-6ec7-4683-fdasfasdf-2324234234"
}, {
"Name": "email",
"Value": "test.user#email.com"
}, {
"Name": "custom:var",
"Value": "VALUEIWANT"
}],
"Username": "testuser"
}
const index = x.UserAttributes.findIndex(item => item.Name === "custom:var");
const y = x.UserAttributes[index].Value;
console.log(y);
An helper function for this would be like below
const x = {
"UserAttributes": [{
"Name": "sub",
"Value": "54f5cdfb-6ec7-4683-fdasfasdf-2324234234"
}, {
"Name": "custom:var",
"Value": "VALUEIWANT"
}, {
"Name": "email",
"Value": "test.user#email.com"
}],
"Username": "testuser"
}
function getValue(x, name) {
const index = x.UserAttributes.findIndex(item => item.Name === name);
return index === -1 ? null : x.UserAttributes[index].Value;
}
// get email
console.log(getValue(x, 'email'));
// get custom:var
console.log(getValue(x, 'custom:var'))
Use Array.find on the x.UserAttributes array to search for the item with name of "custom:var", and take the value:
const valueYouWant = x.UserAttributes.find(ua => ua.Name === "custom:var").Value;
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.
I've started with simply pulling in an array and mapping over the values, setting to state and then displaying on screen using conventional react and javascript methods
Now I want to rebuild this with rxjs
{
"countriesList": [
{
"name": "Australia"
},
{
"name": "Austria"
},
{
"name": "Beligum"
},
{
"name": "Belize"
},
{
"name": "Brazil"
},
{
"name": "Cameroon"
},
{
"name": "Denmark"
}
]
}
const countries$ = of(countriesList) // this returns the array above
but then I want to filter this list when I start typing values. typically I would build a function, and then filter based on the input. but struggling to replicate this with rxjs
I've tried the following and keep getting countries.map is not a function
return countries$.subscribe((countries) => countries)
I also tried this:
countries$.pipe(map((country) => country.filter((ctry) => ctry.name.toLowerCase().startsWith(e.target.value))))
whereby I want to map then filter and return the values that start with the letters typed in
not really getting the hang of this
any ideas?
Ok for starters I am trying to learn rxjs lately so I hope my example will help you understand the differences between of and from.
Also it would be nice to review the of and from "creators".
const { from, of, pipe } = rxjs;
const { map, filter } = rxjs.operators;
console.clear();
const countries = [
{
"name": "Australia"
},
{
"name": "Austria"
},
{
"name": "Beligum"
},
{
"name": "Belize"
},
{
"name": "Brazil"
},
{
"name": "Cameroon"
},
{
"name": "Denmark"
}
];
const countriesFrom$ = from(countries);
const countriesOf$ = of(countries);
console.log("----stream from----")
countriesFrom$.subscribe(val => console.log(val));
console.log("----stream of----")
countriesOf$.subscribe(val => console.log(val));
const countries$ = from(countries);
console.log('----filtering----');
countries$.pipe(
filter(country => country && country.name && country.name.startsWith('A')),
map(console.log)
).subscribe()
basically of unlike from, it does not do any flattening and emits each argument in whole as a separate next notification
I'd like to know if one can use .map() to dynamically change the added value to JS objects.
For example, a static use of .map() allows to add a similar ID to all objects of the array.
friends = [
{
"age": 10,
"name": "Castillo"
},
{
"age": 11,
"name": "Daugherty"
},
{
"age": 12,
"name": "Travis"
}
]
// Static mapping --> adds 1 to all objects
friends_static=friends;
friends.map(elem => elem["id"] = 1);
console.log(friends_static)
This returns [{age=10, name="Castillo", id=1}, {age=11, name="Daugherty", id=1}, {age=12, name="Travis", id=1}]
Is it possible to add a unique ID which increments by 1 for each object in a similar way?
Cf. the illustrative JSfiddle and example code below. I know the 1++ is not legal, but just shows the idea I'm trying to realize.
//Dynamic mapping? --> should add 1,2,3...to objects incrementally
/*
friends_dynamic=friends;
friends.map(elem => elem["id"] = 1++);
console.log(friends_dynamic)
*/
This should return [{age=10, name="Castillo", id=1}, {age=11, name="Daugherty", id=2}, {age=12, name="Travis", id=3}]
You could just use the index provided to the Array#map callback:
friends.map((friend, index) => Object.assign({}, friend, { id: index + 1 }))
It's not a good idea to mutate objects in Array#map. The whole purpose of the method is to return new objects that are mapped from the original objects. Thus use Object.assign to avoid mutation.
Of course, if you wanted mutation, thus just use forEach without mapping to new values. It would be more "semantically correct" in that case.
Is this what you mean?
const friends = [
{
"age": 10,
"name": "Castillo"
},
{
"age": 11,
"name": "Daugherty"
},
{
"age": 12,
"name": "Travis"
}
]
friends.forEach((friend, index) => friend.id = index + 1);
console.log(friends)
if you only need an incremental value from 0 on, you can simply use a counter and increment it, like this:
let id = 1;
friends.map(elem => {elem.id = id++;});
Use a local variable and increment it. As per method definition
"The map() method calls the provided function once for each element in an array, in order". In Order would make sure that ids do not collide.
friends = [
{
"age": 10,
"name": "Castillo"
},
{
"age": 11,
"name": "Daugherty"
},
{
"age": 12,
"name": "Travis"
}
]
// Static mapping --> adds 1 to all objects
friends_static=friends;
var i = 1;
friends_static.map(elem => elem["id"] = i++);
console.log(friends_static)
//Dynamic mapping? --> should add 1,2,3...to objects incrementally
/*
friends_dynamic=friends;
friends_dynamic.map(elem => elem["id"] = 1++);
console.log(friends_dynamic)
*/