Dynamically return specific attribute from an object - reactjs

I'm trying to create a function that will return the needed attribute from an object.
The object will look like this:
export var Characters = [
{
id: 1,
Name: "Abe",
HitPointValue: "124",
StrengthValue: "12",
IntelligenceValue: "14",
WisdomValue: "16",
DexterityValue: "12",
ConstitutionValue: "10",
CharismaValue: "17",
Avatar: require('./images/avatar_7.jpg')
}
]
I tried this:
export function getStat(id, stat) {
var idx = Characters.findIndex((val) => val.id == id);
return Characters[idx].stat;
}
For example, let's say I need to get the "WisdomValue" of this object.
So I call it like this:
<Text style={[styles.stats]}>
{"\n"}
Wisdom Value: {getStat(1, 'WisdomValue')}{"\n"}
</Text>
But I just get an error 'undefined is not an object'
How can I get just one specific attribute, but in a dynamic way? So I don't have to write a separte function like, getHitPointValue(id), get StrengthValue(id), etc...
thanks!

Use [] instead of using dot notation, because you are trying to access a value by a dynamic key.
Check this snippet:
var Characters = [
{
id: 1,
Name: "Abe",
HitPointValue: "124",
StrengthValue: "12",
IntelligenceValue: "14",
WisdomValue: "16",
DexterityValue: "12",
ConstitutionValue: "10",
CharismaValue: "17",
}
]
function getStat(id, stat) {
var idx = Characters.findIndex((val) => val.id == id);
if(idx >= 0)
return Characters[idx][stat];
else return "not found"
}
console.log(getStat(1, 'WisdomValue'));
console.log(getStat('15', 'abc'));

var Characters = [
{
id: 1,
Name: "Abe",
HitPointValue: "124",
StrengthValue: "12",
IntelligenceValue: "14",
WisdomValue: "16",
DexterityValue: "12",
ConstitutionValue: "10",
CharismaValue: "17",
}
]
function getStat(id, stat) {
// you can directly find the object rather going through the array index
var character = Characters.find((val) => val.id == id);
// care for non existing characters
if (!character) {
throw new Error(`Character with id ${id} does not exist`);
}
// care for non existing stats
if (!character.hasOwnProperty(stat)) {
throw new Error(`Stat ${stat} is not available for character with id ${id}`);
}
// use the [] notation as opposed to the dot notation when evaluating dynamic property names
return character[stat];
}
console.log(`Wisdom Value: ${getStat(1, 'WisdomValue')}`);
console.log(`Charisma Value: ${getStat(1, 'CharismaValue')}`);
try {
console.log(getStat(2, 'Name'));
} catch (e) {
console.log(e.message);
}
try {
console.log(getStat(1, 'PersuasionValue'));
} catch (e) {
console.log(e.message);
}

Related

How to update old value with new value in array [React native]

I have array
[{
"studentname": "abc",
"marks": "20"
},
{
"studentname": "abc2",
"marks": "20"
}
]
I have want add 10 more marks where studentname=abc into marks so how do this
eg.10+20=30
so the output will be
[{
"studentname": "abc",
"marks": "30"
},
{
"studentname": "abc2",
"marks": "20"
}
]
const updatedArray = array.map(item => {
if (item.studentname === "abc") {
return {
studentname: "abc",
marks: parseInt(item.marks, 10) + 10
};
} else {
return item;
}
});
This is one clean way to do it.
const x= [{
"studentname": "abc",
"marks": "20"
},
{
"studentname": "abc2",
"marks": "20"
}
]
x.forEach(function(obj) {
if (obj.studentname === 'abc') {
obj.marks = Number(obj.marks) + 10
}
});
console.log(x)
const array= [{
"studentname": "abc",
"marks": "20"
},
{
"studentname": "abc2",
"marks": "20"
}
]
array.map((item,index)=> {
if (item.studentname == 'abc') {
item.marks = Number(item.marks) + 10
}
});
console.log("Your Updated Array Here:->",array)
Loop through the array of objects
Check if the studentname property of the current object is equal to abc
If it is, add 10 to the marks property of the current object
After the loop, the array will be updated with the modified object
const arr = [{"studentname": "abc", "marks": "20"},
{"studentname": "abc2","marks": "20" }];
for (let i = 0; i < arr.length; i++) {
if (arr[i].studentname === "abc") {
arr[i].marks = parseInt(arr[i].marks) + 10;
}
}
console.log(arr);

I can't use filter when I have objects inside an array and find last id, angular

I need your opinion in this situation:
I get from API with this function:
getRS(
idProject: string
): Observable<ResponseModel<RSModel>> {
return this.http.get<ResponseModel<RSModel>>(
ApiUrlsConfig.getRS(
idProject
)
);
}
this response:
{
"data": [
{
"id": "id1",
"state": 1,
"note": null
},
{
"id": "id1",
"state": 2,
"note": "Reason 1"
},
{
"id": "id2",
"state": 2,
"note": "Reason updated3",
}
],
"result": null
}
I need to use filter in this response because I should be get the last state for each id. For example, I want to display state 2 in item with id: id1. For this I want to use filter. The problem is because I can't use filter on it, I don't understand why.
I tried to write this code:
#Input() set jobId(jobId: string) {
this.optionsService
.getRS(
this.idProject
)
.pipe()
.subscribe((res) => {
let resId = res.filter((aaa)=>{
if(aaa.id === jobId){
res.slice(-1)[0].id
}
}
)
});
}
Not function.
Please can you share with me any idea?
Thank you
Try this logic:
Loop backwards throw it.
Loop backwards over index to the start.
Splice duplicates.
let response = {
"data": [
{
"id": "id1",
"state": 1,
"note": null
},
{
"id": "id1",
"state": 2,
"note": "Reason 1"
},
{
"id": "id2",
"state": 2,
"note": "Reason updated3"
}
],
"result": null
}
let data = response.data;
for (let i = data.length - 1; i >= 0; i--) {
for (let j = i - 1; j >= 0; j--) {
if (data[i].id === data[j].id) {
data.splice(j, 1);
j++;
}
}
};
console.log(data);
try this:
if(aaa.id == jobId){
return res.slice(-1)[0].id
}

Updating state of deep object value in React/Redux using immutable.js

I have this pretty deeply nested state array and need to update the Hours field by Employee, Task, and Week. I've attempted numerous ways to do this with Immutable but not having success, any help?
Here is an example of my data :
[{
"Employee": "John Doe",
"Other Data": "test",
"Tasks": [{
"AccessType": "Confidential",
"DueDate": "2016-02-26 23:59:59",
"taskId": "3",
"TaskTitle": "testTitle",
"Weeks": {
"2016-10-10": {
"Hours": "3"
}
}
}]
}, {
"Employee": "Bill Der",
"Other Data": "test",
"Tasks": [{
"AccessType": "Confidential",
"DueDate": "2016-02-26 23:59:59",
"taskId": "3",
"TaskTitle": "testTitle",
"Weeks": {
"2016-10-10": {
"Hours": "3"
}
}
}]
}]
You are missing a bunch of information for me to fully answer this for you, but I can show you how I would do something like this otherwise.
You can take advantage of all the functions immutable js provides you with. So lets say you have an object with the information needed to mutate your immutable object, something like this :
var changeHours = {
"Employee": "John Doe",
"TaskTitle": "testTitle",
"Week": '2016-10-10',
"Hours": "5"
}
And we have a basic state like you have there set up like this :
var myState = Immutable.fromJS([{
"Employee": "John Doe",
"Tasks": [{
"AccessType": "Confidential",
"DueDate": "2016-02-26 23:59:59",
"taskId": "3",
"TaskTitle": "testTitle",
"Weeks": {
"2016-10-10": {
"Hours": "3"
}
}
}]
}]);
Note: I did not add more the the arrays, but we will map over them so they will be taken into account.
You can use immutables map to iterate over and find the items you are looking for, something like this :
var newstate = myState.map((k, v) => {
if (k.get('Employee') === changeHours.Employee) {
return k.get('Tasks').map((k, v) => {
if (k.get('TaskTitle') === changeHours.TaskTitle) {
return k.setIn(['Weeks', changeHours.Week, 'Hours'], changeHours.Hours);
}
return k;
})
return k;
}
return k;
});
To see it in action - http://fiddle.jshell.net/djj6u8xL/63/ . I am iterating over each array level with map and finding the correct node by checking based on our changeHours object and immutables get, then once I am at the right level I just use setIn. You can use updateIn as well, it just depends on your scenario.
In the future, please provide all the information for your question, not just a picture of the data, it will be much easier to help you :) (and not have to type out the data structure manually).
Edit: Update based on comment - http://fiddle.jshell.net/qxbq1nq3/9/
the code :
function newTasks(k) {
return k.get('Tasks').map((k, v) => {
if (k.get('TaskTitle') === changeHours.TaskTitle) {
return k.setIn(['Weeks', changeHours.Week, 'Hours'], changeHours.Hours);
}
return k;
});
}
var newstate = myState.map((k, v) => {
if (k.get('Employee') === changeHours.Employee) {
return k.set('Tasks', newTasks(k));
}
return k;
});

How to modify a complex JSON Object in using Immutable

I have below JSON and wanted to update the value depending on Aid, Bid and Cid using Immutable.js
e.g.
Below input provided.
Aid= A, Bid = 1, Cid= 4, NewValue = 'FOUR'
If above input is provided the value "One" needs to be changed to "FOUR"
let sampleJson = {
Aid: 'A', detail:"sample", list: [
{
"Bid": "1",
"group": [
{
"name": "Group A",
"Cid": "4",
"value": "One"
},
{
"name": "Group A",
"Cid": "41",
"value": "1"
},
]
},
{
"Bid": "2",
"group": [
{
"name": "Group A",
"Cid": "4",
"value": "1"
},
{
"name": "Group A",
"Cid": "4",
"value": "1"
},
]
};
I was able to access the value using below code. How can i return the entire JSON with updated value?
let variale = Immutable.fromJS(sampleJson).
getIn(['list']).
find(allocation => allocation.get("Bid") === "1").
getIn(['group']).
find(fun => fun.get("Cid") === "4").set('value',"FOUR");
Anyone has any suggestions on how to resolve this problem?
I think you can try to do this like so:
let immutable = Immutable.fromJS(sampleJson);
immutable = immutable.setIn(['list', 0, 'group', 0, 'value'], 'FOUR');
This monstrosity is how I would do it:
const newData = originalData.update('list', list => {
const itemIndex = list.findIndex(item => item.get('Bid') === '2');
return list.update(itemIndex, listItem => {
return listItem.update('group', groupList => {
const groupIndex = list.findIndex(group => group.get('Cid') === '4');
return groupList.update(groupIndex, group => {
return group.set('value', 'FOUR');
});
});
});
});
https://jsbin.com/latupo/7/edit?html,js,console
Personally I stopped using Immutable, I always found it a bit painful (not to mention those docs!). I now use redux and good old cloning to not mutate state. Less performant in theory but if you've got nothing that runs over a few milliseconds anyway, save yourself the trouble...

fetch array values using sports_id

I have a function that returns an array of objects data.sportdata. I would like to get all array elements with the same sports_id. The code
$scope.arrSportData = data.sportdata;
angular.forEach($scope.arrSportData, function(value, key) {
console.log($scope.arrSportData);
//getting reponse
/*
Object { id: "1", user_id: "2", sport_id: "1", position_id: "1", team_name: "JimmyTmname",}
Object { id: "2", user_id: "2", sport_id: "2", position_id: "6", team_name: "JimmyTmname2",}
Object { id: "3", user_id: "2", sport_id: "3", position_id: "12", team_name: "JimmyTmname3",}
Object { id: "4", user_id: "2", sport_id: "5", position_id: "20", team_name: "JimmyTmname5",}
*/
//code i wrote
if (value.sport_id == 1) {
$scope.positionId.spr1 = value.position_id;
$scope.teamname.spr1 = value.team_name;
}
if (value.sport_id == 2) {
$scope.positionId.spr2 = value.position_id;
$scope.teamname.spr2 = value.team_name;
}
if (value.sport_id == 3) {
$scope.positionId.spr3 = value.position_id;
$scope.teamname.spr3 = value.team_name;
}
if (value.sport_id == 4) {
$scope.positionId.spr4 = value.position_id;
$scope.teamname.spr4 = value.team_name;
}
});
Here I am always getting first value and nothing more. Please suggest and help to solve this problem.
I did try outside of the loop but does not work. I think filter function can do this but dont know how does it work.
Perform a groupBy function which will give you an object like this
{
key: [],
key: []
}
Here the key will be sport_id and [] will be the items with the same key.
A minimal working example will be,
// Written By: Ceaser Bautista
//Link: http://stackoverflow.com/a/34890276/17447
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
//here we have four teams with two sports id 13 and 22
var arrSportData = [{
id: "1",
user_id: "1",
sport_id: "13",
position_id: "1",
team_name: "JimmyTmname"
}, {
id: "2",
user_id: "2",
sport_id: "22",
position_id: "6",
team_name: "JimmyTmname2"
}, {
id: "3",
user_id: "3",
sport_id: "22",
position_id: "12",
team_name: "JimmyTmname2",
}, {
id: "4",
user_id: "4",
sport_id: "13",
position_id: "20",
team_name: "JimmyTmname1"
}];
$scope.groupedData = groupBy(arrSportData, "sport_id");
console.log(groupedData);
Now you will have an array for each sports_id. In view populate it like
<div ng-repeat="(key, items) in groupedData">
<h4>Sports ID: {{key}}</h4>
<ul ng-repeat="item in items">
<li>User ID: {{item.user_id}}</li>
</ul>
</div>

Resources