React native: how to find an item in array? - reactjs

i have this array:
var arr = [{"3": "2"}, {"2": "6"}, {"4": "7"}, {"5": "9"}];
I cant get the value by index, i am trying to do this:
console.log(arr[3]); //output needed: 2.
console.log(arr[5]); //output needed: 9.
...
any help please?
UPDATE:
I am trying to add sub categories to an array with the main category:
const [subcatsSelectedForNow,setSubCatsSelectedForNow]=useState([]);
const selectCat = (catid,maincat)=>{
var arr=subcatsSelectedForNow || [];
arr.push({
[catid]:maincat
});
setSubCatsSelectedForNow(arr);
};

const arr = [{ 3: "2" }, { 2: "6" }, { 4: "7" }, { 5: "9" }];
You simply can't achieve your accepted behavior using console.log(arr[3]);
First you need to find whether the property(catid) exist in the array or not & if it is exist then you can get the object value as below,
const find = (num) => {
let obj = arr.find((item) => item[num]);
return obj && obj[num];
};
console.log(find(3)); //Output -> 2
Hope this helps you. Feel free for doubts.

Related

How to return objects that have matching value when comparing to a separate array

In my state I have an object called foodLog which holds all entries a user enters with one of the keys being foodSelectedKey and I'm trying to return all entries that have a matching value from that key with a different array called foodFilter.
However, this doesn't work and errors out saying foodLog.filter() isn't a function - I've looked this up and it's because it's an Object (I think). Any help would be greatly appreciated!
state = {
// log food is for the logged entries
foodLog: {},
// used for when filtering food entries
foodFilter: [],
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.filter((item) => {
return foodLog.foodsSelectedKey.map((food) => {
return foodFilter.includes(food);
});
});
};
I guess the reason behind the error Is not a function is that the object can not be looped. By that it means you can not iterate an object with differend variables inside, if it has no index to be iterated like an array. The same goes for map(), find() and similar functions which MUST be run with arrays - not objects.
As far as I understand you have an object named foodLog which has an array named foodsSelectedKey. We need to find intersected elements out of foodFilter with the array. This is what I came up with:
state = {
// log food is for the logged entries
foodLog: {
foodsSelectedKey: [
{ id: 1, name: "chicken" },
{ id: 2, name: "mashroom" }
]
},
// used for when filtering food entries
foodFilter: [
{ id: 1, name: "chicken" },
{ id: 2, name: "orange" }
]
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.foodsSelectedKey.filter((key) =>
{
for (let i=0; i<foodFilter.length;i++){
if(foodFilter[i].name===key.name)
return true
}
return false;
}
);
return matched;
};
The Output is filtered array, in this case, of one element only:
[{
id: 1
name: "chicken"
}]
In order to check the output - run console.log(findMatches()). Here is the CodeSandbox of the solution. (check console at right bottom)

Sorting an array which contains string object in react

I'm retrieving the data from the radio button checked for database purposes and I wanted to check the string objects index are equal to the api response string object from the db. The user can select the radio button in any order, but finally I wanted to sort the radio button with respect to get api response
Since, I'm new to react, I am trying to start off with...
I have attached the response below
data:
matrix:
option_questions: Array(10)
0: {text: "Hai"}
1: {text: "Hello"}
2: {text: "Hola"}
options: Array(10)
0: {text: "1"}
1: {text: "2"}
2: {text: "3"}
After checking the radio button values, my array goes likes this...
0:
id: "3"
qn: "Hello"
1:
id: "1"
qn: "Hola"
2:
id: "2"
qn: "Hai"
Here, I have to rearrange the array using the qn object index only like below format..
0:
id: "2"
qn: "Hai"
1:
id: "3"
qn: "Hello"
2:
id: "1"
qn: "Hola"
This is my code for on change
changeRadioHandler = (event) => {
const qn = event.target.name;
const id = event.target.value;
const question = {
id: event.target.value,
qn
};
if (this.state.questions.some((question) => question.qn === qn)) {
questions = [
...this.state.questions.filter((question) => question.qn !== qn),
question,
];
} else {
questions = [...this.state.questions, question];
}
const comparator = (a, b) => a.qn.localCompare(b.qn);
console.log(questions.sort(comparator), "comparator");
questions.sort(comparator);
this.setState({ questions });
console.log(questions);
};
Create a comparator function to compare the qn properties of each element and do a localeCompare comparison.
const comparator = (a, b) => a.qn.localeCompare(b.qn);
const data = [
{
id: "3",
qn: "Hello"
},
{
id: "1",
qn: "Hola"
},
{
id: "2",
qn: "Hai"
},
];
const comparator = (a, b) => a.qn.localeCompare(b.qn);
console.log(data.sort(comparator));

Devide list from database into multiple section (React)

I am currently struggling with this problem. Hopefully, you can help me :)
Data is selected from a Database and it returns Objects structured like this:
object = {
id: 4,
name: "Banana",
idParent: 1
}
idParent would be the section of the product.
There are a lot of products and a lot of sections so a simple
const sectionOne = [];
ObjectList.map(e => {
if(e.idParent === 1) {
sectionOne.push(e);
}
})
would probably be wrong, because it should be possible to add other idParents in the future and code should not need some rework in that case.
Let's say there are 30 Objects, 10 have idParent = 1, 15 have idParent = 2 and the last 5 have idParent = 3.
How can the whole list be divided into these sections without making a variable for each section?
Thanks for the help :)
What I believe you need here is a map which groups the values of the list by idParent.
Example:
const objectList = [{
id: 4,
name: "Banana",
idParent: 1
},
{
id: 3,
name: "apple",
idParent: 2
},
{
id: 5,
name: "orange",
idParent: 2
}];
const groupBy = (array, key) => {
return array.reduce((accumlator, value) => {
(accumlator[value[key]] = accumlator[value[key]] || []).push(value);
return accumlator;
}, new Map());
};
const resultMap = groupBy(objectList, "idParent");
console.log(resultMap);
enter code here
The sub-arrays from the map can be access also like this:
const groupWihtIdParen1 = resultMap[1];
// or like this
const groupWithIdParent2 = resultMap.get(2);
``

typescript how to find inside an array that is already in an array?

I want to find a value inside an array that is already inside an array.
To give an example of my array:
[
{
ConcessionId: 1,
ConcessionName: "Coyotes",
KnownAs: [
{
TeamId: 1,
Name: "Arizona Coyotes",
},
{
TeamId: 2,
Name: "Phoenix Coyotes",
}
]
},
{
ConcessionId: 2,
ConcessionName: "Devils",
KnownAs: [
{
TeamId: 3,
Name: "Colorado Rockies",
},
{
TeamId: 4,
Name: "New-Jersey Devils",
}
]
}
]
What I want is when Icall my function it returns me the team name.
For example, I the parameter value is 3, I want Colorado Rockies as a name:
public getInfo(_TeamID) {
const concession: ConcessionInfo[] = this.concessionList$.filter(function (x) {
x.KnownAs.filter( (y)=> {
y.TeamId= +_TeamID;
return y.Name;
})
})
}
I try so many different way with filter. But never get something good. Never works.
I can make a double .foreach , for each array. but I think a better method exist than making a double loop.
Thanks
Instead of using the filter method (which is in fact working similar as a for loop), you could do forEach on both arrays. For your current data structure, there is no other way around it.
getInfo = (_TeamID) => {
let teamName = '';
this.concessionList$.forEach(entry => {
entry.KnownAs.forEach(team => {
if(team.TeamId === _TeamID){
teamName = team.Name;
return; // break the loop.
}
})
});
return teamName;
}
Here is a working example
https://stackblitz.com/edit/double-for-lopp
EDIT
If you have a look at the polyfill implementation of filter from Mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter which is in equivalent to the native implementation of filter, you can see that it is looping through the whole array, the same way as a forEach loop. The difference is that the filter method will return a new array based on the boolean condition inside the callback function, while a forEach loop does not return anything.
Assuming myArray is contains the data you provided.
The following code will work if you're using Typescript 3.7 and above.
public getInfo(teamId: number): string | undefined {
const team = this.concessionList$
.map(concession => concession.KnownAs)
.reduce((a, b) => a.concat(b), [])
.find(team => team.TeamId === teamId)
return team ? team.Name : undefined
}
Usage:
this.getInfo(3) // Colorado Rockies
Ok how this work?
You have to understand what is find. For example:
const result = [{name: 'foo', age: 1}, {name: 'bar', age: 2}]
.find(people => people.name === 'foo')
console.log(result) // {name: 'foo', age: 1}

Merge arrays with condition

I would like to merge two arrays with specific condition and update objects that they are containing.
First my struct that is in arrays:
struct Item {
var id:Int
var name:String
var value:Int
}
Second elements for the two arrays:
let fisrt = Item(id: 1, name: "Oleg", value: 3)
let second = Item(id: 2, name: "Olexander", value:5)
let fisrtInSecond = Item(id: 1, name: "Bogdan", value: 6)
let secondInSecond = Item(id: 2, name: "Max", value: 9)
Arrays:
var fisrtArray = [fisrt, second]
let secondArray = [fisrtInSecond, secondInSecond]
I woudl like to use zip and map functions of the collection to achive result. Result is that fisrtArray elements names are updated by id.
Example: fisrtArray = [Item(id: 1, name: "Bogdan", value:3), Item(id: 2, name: "Max", value:5)]
I know how to do this via simple loops. But i am looking for more advanced usage of the functional programing is Swift.
My experiment:
fisrtArray = zip(fisrtArray, secondArray).map()
The main problem i do not know how to write condition in the map function. Condition should be:
if ($0.id == $1.id) {
$0.name = $1.name
}
From the comment discussing it is possible to highlight that zip is not suitable in my case because we should iterate over all array to find if we have similar id's that are not in the same order.
The following code does work independently by the order of the elements inside the 2 arrays
firstArray = firstArray.map { (item) -> Item in
guard
let index = secondArray.index(where: { $0.id == item.id })
else { return item }
var item = item
item.name = secondArray[index].name
return item
}
"[Item(id: 1, name: "Bogdan", value: 3), Item(id: 2, name: "Max", value: 5)]\n"
Update
The following version uses the first(where: method as suggested by Martin R.
firstArray = firstArray.map { item -> Item in
guard let secondElm = secondArray.first(where: { $0.id == item.id }) else { return item }
var item = item
item.name = secondElm.name
return item
}
A solution for your specific problem above would be:
struct Item {
var id: Int
var name: String
}
let first = Item(id: 1, name: "Oleg")
let second = Item(id: 2, name: "Olexander")
let firstInSecond = Item(id: 1, name: "Bogdan")
let secondInSecond = Item(id: 2, name: "Max")
let ret = zip([first, second], [firstInSecond, secondInSecond]).map({
return $0.id == $1.id ? $1 : $0
})
=> But it requires that there are as many items in the first as in the second array - and that they have both the same ids in the same order...
The map function cannot directly mutate its elements. And since you're using structs (passed by value), it wouldn't work anyway, because the version you see in $0 would be a different instance than the one in the array. To use map correctly, I'd use a closure like this:
fisrtArray = zip(fisrtArray, secondArray).map() {
return Item(id: $0.id, name: $1.name, value: $0.value)
}
This produces the result you're expecting.
Now, if your structs were objects (value types instead of reference types), you could use forEach and do the $0.name = $1.name in there.

Resources