Break map() function in React JS based on condition - javascript

Requirement: Basically I have an array of employee object in React JS, say empList. This empList contains primitive fields & again an inner array of another "address" objects, say addressList. I want to fetch data for all employees if they belong to city "ABC". They can have multiple address in city "ABC", but they should be fetched only once & pushed into finalList only once.
Problem : I am able to filter the employees having address in city "ABC" but in case, they have multiple address in city "ABC", then they are added to the finalList multiple times. So, I want to check for all addresses for an employee & in case, any one is found in city "ABC", I want to add it to finalList, break this inner map() function & go to outer map() to check for next employee.
Below is my code snippet.
var finalList =[];
empList.map(function(employee) {
var valid = employee.addressList.map(function(address) {
if (address.city.startsWith("ABC")) {
finalList.push(employee);
//Employee pushed to validList once, so now break from inner map() function & goto second line/execute on next employee object
}
}); //.slice(0,1); Slice doesn't work here since I want the condition to be true first, then break it.

You can use the some which tests whether at least one element in the array passes the test condition.
Read about some here.
var finalList = empList.filter(e => e.addressList.some(a => a.city.startsWith("ABC")));
Also I've updated your logic to use filter (instead of map) which creates a new array with all elements that pass the provided condition.
You can read about filter at here.

Related

Get API array number by comparing ''Name''

I want to compare the name of a button I press with an array to find the matching name and then select that array number.
I currently have a For loop which gets all the info from every team in the array but I only need a specific one.
for( var i = 0 ; i <data.api.teams.length; i++)
.lenght needs to be the value corresponding to the team name I selected.
So for example: I press a button with the name and value of ''Twente'', I want the a for loop to search through the names to find ''Twente'' and return the number (''6'') as a value in order to use in another loop.
Does anyone know how I can handle this request?
The screenshot shows the API data I get from the call to get all the info I need.
To get array index of the item you can use Array.findIndex
teamIndex = data.api.teams.findIndex(
team => team.name == "Twente";
);
You're making this more complicated than you need to- you don't need a manual loop, just use Array.prototype.findIndex().
From MDN:
The findIndex() method returns the index of the first element in the array that satisfies the provided testing function. Otherwise, it returns -1, indicating that no element passed the test.
In your case, we'll pass findIndex() a function checking for the name match.
data.api.teams.findIndex(team => team.name == name);

How to use a index value of a dynamic array (which get filled by a click event) for filtering a new array

I'm working on a filter, which filters a array of nested arrays down to the value of one last index.
This happens in 5 steps. At each step you choose which index value (string) get used to filter the array further.
Example: You have 5 categories, each have 6 themes. Each of these 6 themes has 6 focusses(sub themes). Each focus has 6 questions. Each question has 1 answer. First you pick a categorie. This narrows the arrays down to all arrays with that categorie. Then a theme, which narrows the array down to only the arrays with that theme... etc...
So far I managed to filter down to the right question.
You can find the code here: https://github.com/okestens/vertical-filter.git
To get this work, I hardcoded the string "Deskundigheid" as a condition for the equality operator (===) that get used for the filter.
Example:
// FILTER QUESTIONS // I tried to use state.focus[0] but it does not work
let unique_questionsA = [. // now this is hardcoded
...new Set(formsA.filter((i) => i[2] === "Deskundigheid").map((i) => i[3])),
]; --------------
// FUNCTION
function displayQuestionsA() {
state.questions = [];
unique_questionsA.forEach(function (question, index) {
document.getElementById("question" + index).innerHTML = question;
state.questions.push(question);
});
------
// the state object
let state = {
category: [],
themes: [],
focus: [],
question: [],
answer: [],
};
But. What I want this filter to use is not a hardcoded string (deskundigheid) but the exact string that is visible in the div (coming from a click event which creates this filtered array and get stored in the state object). See image.
I thought: I need to track these arrays (with an object called 'state', capturing these dynamic arrays). If I then want to filter the right questions, by using the value (string) of the chosen focus (For example 'Deskundigheid', which is visible to the user), I just refer to the corresponding index value (state.focus[0]) of that chosen focus string, coming from the dynamic state object.
But, if I use the index state.focus[0] for the filter which creates the questions array, I get an empty array :(
My thought: Although the empty focus array (inside the state object), which get filled by a click event, eventually is filled with the right strings, the filter for the new array (unique_questionsA), which uses 'state.focus[0]' does not read the filled array as ‘filled’ but as empty.
I have not idea why :(
I hope I'm clear. If so, and you maybe have a clue, I would love to have a chat! Thanks O
The question can be summed up to
how do I get the text of the element when clicked, in an onclick event
listener callback function.
Your focusScript.js can be modified to
function displayQuestionsA(e) {
state.questions = [];
let unique_questionsA = [...new Set(formsA.filter((i) => i[2] === e.target.innerText).map((i) => i[3]))];
}
document.querySelector(".focus__A").addEventListener("click", displayQuestionsA);
Notice the e.target.innerText which contains the text inside the element that triggered the event(which you clicked).
if I got you correctly - both map and filter functions can give your callback second parameter - the index.
arr.map((n,i)=>{console.log(`[${i}]:${n}`)})

how to access key/value pairs from json() object?

I'm calling an external service and I get the returned domain object like this:
var domainObject = responseObject.json();
This converts the response object into a js object. I can then easily access a property on this object like this
var users = domainObject.Users
Users is a collection of key/value pairs like this:
1: "Bob Smith"
2: "Jane Doe"
3: "Bill Jones"
But CDT shows users as Object type and users[0] returns undefined. So how can I get a handle to the first item in the collection? I'm assuming that some type of type cast is needed but not sure how I should go about doing this
UPDATE
Here is one way I could access the values:
//get first user key
Object.keys(responseObject.json().Users)[0]
//get first user value
Object.values(responseObject.json().Users)[0]
But I need to databind through ng2 so I was hoping for a simpler way like this:
<div>
<div *ngFor="let user of users">
User Name: {{user.value}}
<br>
</div>
</div>
Maybe I should just create a conversion function in my ng2 component which converts the object into what I need before setting the databinding variable?
UPDATED ANSWER
So after scouring through a few docs I found the "newish" Object.entries() javascript function. You can read about it here. Pretty cool.
Anyways, give this a try. I am ashamed to say that I don't have time to test it, but it should get you going in the right direction.
usersArray = []
// Turn Users object into array of [key, value] sub arrays.
userPairs = Object.entries(users);
// Add the users back into an array in the original order.
for (i=0; i < userPairs; i++) {
usersArray.push(_.find(userPairs, function(userPair) { return userPair[0] == i }))
}
ORIGINAL ANSWER
I would use either underscore.js or lodash to do this. Both are super helpful libraries in terms of dealing with data structures and keeping code to a minimum. I would personally use the _.values function in lodash. Read more about it here.. Then you could use users[0] to retrieve the first item.
The only caveat to this is that lodash doesn't guarantee the iteration sequence will be the same as it is when the object is passed in.
users = _.values(users);
console.log(users[0]);
How about this:
let user= this.users.find(() => true)
This should return the "first" one.
If your initial object is just a plain object, how do you know it is sorted. Property members are not sorted, ie: looping order is nor guaranteed. I´d extract the user names into an array and the sort that array by the second word. This should work (as long as surnames are the second word, and only single spaces are used as separators).
var l=[];
for(var x in users) {
push.l(users[x]);
}
var l1=l.sort ( (a,b) => return a.split(" ")[1]<b.split(" ")[1]);

Adding a different value of the same variable to an array

Using my micro:bit I am trying to add the value of a variable called sendText to an array without overwriting its previous stored value for that variable.
input.onGesture(Gesture.Shake, () => {
list.push(sendText)
binSend = 0
basic.showString(sendText)
})
My array is called list
let list: string[] = []
I am trying to store single characters in an array then outputting them. If there is a better alternative to using an array I would gladly accept it.
To add a value to an array you use push function, after, if you need to group the characters pushed to array for output you could to use for your specific example list.join('')

Display different text everytime you call onclick function

I have this code where I am trying to pull users from my firebase database:
function pullFromDB(){
usersRef.on('value', function(snapshot) {
function next_user(){
for (user in snapshot.val().users){
document.getElementById("users").innerHTML = user
}
}
So far it will return just one of the users as I believe it must be going through the whole users array and then putting the last name into the "users" element.
How can I iterate to the next item in the array and display a different name every time I click a button?
I have no idea what's return from DB but first try the console.log() to see what's the type of result. This will give you the answer if you are working on array or other data type.
Then if it's an array, your code:
for (user in snapshot.val().users){
document.getElementById("users").innerHTML = user
}
It iterates the whole array and .innerHTML puts user string as the last iteration. If you want to change it each time you click a button you need a variable that will contain inteager of index that's currently aplied to id="users".
Then for each click you need to increase the variable by one.
Here is an example of working with arrays in JS. http://www.w3schools.com/js/tryit.asp?filename=tryjs_array_element
Your are iterating through the whole array and only the last one is possible shown. You just need to assign an index and use it.
I don't know your remaining code, but by the given information, this should to the trick:
i = 0;
function pullFromDB(){
usersRef.on('value', function(snapshot) {
lastnames = Object.keys(snapshot.val().users); // get all keys, in your case the last names
function next_user(){
user = lastnames[i];
document.getElementById("users").innerHTML = user;
i++; // increase after click
// when you want to access more information of the user, you can do it like this (as an example)
// user_id = snapshot.val().users[user].id;
}

Categories

Resources