Testing values of array objects - javascript

If i have an array like:
[
{ "user": "tom",
"email": "ee#co.com"
},
{ "user": "james",
"email": "bb#co.com"
},
{ "user": "ryan",
"email": "rr#co.com"
}
]
But it's not always being returned in that order - how can i check if ryan, for example, exists somewhere in one of these objects?

If you are already using lodash (or want to) then I would use its find:
_.find(array, { user: "ryan" })
Or with a few more characters you can do it without lodash:
array.find(elem => elem.user === "ryan")
Both return undefined if a matching element is not found.

Function return true if array contains ryan.
var input = [
{ "user": "tom",
"email": "ee#co.com"
},
{ "user": "james",
"email": "bb#co.com"
},
{ "user": "ryan",
"email": "rr#co.com"
}
]
var output = input.some(function(eachRow){
return eachRow.user === 'ryan';
});
console.log(output);

My method to solve that is to extract the targeted fields into arrays then check the value.
const chai = require('chai');
const expect = chai.expect;
describe('unit test', function() {
it('runs test', function() {
const users = [
{ "user": "tom",
"email": "ee#co.com"
},
{ "user": "james",
"email": "bb#co.com"
},
{ "user": "ryan",
"email": "ryan#co.com"
}
];
const names = extractField(users, 'user'); // ['tom', 'james', 'ryan']
expect(names).to.include('ryan');
});
function extractField(users, fieldName) {
return users.map(user => user[fieldName]);
}
});
I'm using chai for assertion. In case you want to check in other fields, we just use the extract methods.
const emails = extractField(users, 'email');
expect(emails).to.include('ryan');
Hope it helps

Related

Map a new key-value pair into an array of objects

I would like to add a new key-value pair to all objects within my data. The structure looks like this:
userData:
[
{
"id": 1,
"name": "John Doe",
"email": "xyz.com"
},
{
"id": 2,
"name": "Jane Doe",
"email": "zzz.com"
},
{
"id": 3,
"name": "Anne Doe",
"email": "yyy.com"
}
]
As a new key-value pair, I would like to add "logged-in": true/false.
To get this data, I use another service. And then I map the true/false values into a variable.
const activeUser = await this.userService.getUserProfile().toPromise();
this.currentUser = activeUser.id;
this.loggedInUser = this.getAccountDetails.map(user => ({
self: this.currentUser === user.id
})
)
Then, I would like to push these key-value pairs into userData.
loggedInUser: { self: boolean }[];
addUserStatus() {
this.userData.map((data, i) => ({ ...data,
"logged-in": this.loggedInUser[i].self
}))
}
What I would like to achieve:
userData:
[
{
"id": 1,
"name": "John Doe",
"email": "xyz.com",
"logged-in": true
},
{
"id": 2,
"name": "Jane Doe",
"email": "zzz.com",
"logged-in": false
},
{
"id": 3,
"name": "Anne Doe",
"email": "yyy.com",
"logged-in": false
}
]
What did I do wrong here?
map returns new data, so your function should look something like this
loggedInUser: { self: boolean }[];
addUserStatus() {
const temp = this.userData.map((data, i) => ({ ...data,
"logged-in": this.loggedInUser[i].self
}))
this.userData = temp
}
If you want to modify this.userData directly, you can use other methods like forEach
addUserStatus() {
this.userData.forEach((data, i) => {
data["logged-in"] = this.loggedInUser[i].self;
};
}
You can simply change the map in addUserStatus to forEach, where you can mutate the entries and add the logged-in property:
addUserStatus() {
this.userData.forEach((data, i) => {
data["logged-in"] = this.loggedInUser[i].self;
};
}

populate hooks with axios json response reactjs

I'm having hard time on thinking how will I populate hooks with API response(json)
see below codes
cosnt [loginResponse, setloginResponse] = useState({
Token: '',
UserID: '', //from user-id
UserName: '', //from user-userName
firstName: '', //from user-firstName
rcCode: '' //from attributes-rcCode
})
const login = async () => {
await axios.get('/API')
.then(response => {
console.log('response.data', response.data.resp)
});
}
here's the result of console.log(response.data.resp)
{
"data": {
"token": "abcd",
"user": {
"id": "123456",
"userName": "uname",
"firstName": "FNAME",
"lastName": "MNAME",
"email": "email#email.com",
"attributes": {
"favorites": ["FAV"],
"rcCode": ["123"]
},
"requiredActions": [],
"roles": ["ROLE"]
},
"modulePermissions": []
}
}
for console.log(response.data):
"resp": {
"data": {
"token": "abcd",
"user": {
"id": "123456",
"userName": "uname",
"firstName": "FNAME",
"lastName": "MNAME",
"email": "email#email.com",
"attributes": {
"favorites": ["FAV"],
"rcCode": ["123"]
},
"requiredActions": [],
"roles": ["ROLE"]
},
"modulePermissions": []
}
},
"success": true
I want to populate my hooks with those datas for me to utilize it on my page.
I got undefined if I tried to console.log(response.data.resp.data)
On console.log(response), I got:
Thank you.
Don't use async/await and .then() together. Use either of those.
const login = async () => {
const response = await axios.get('/API');
const parsedData = JSON.parse(response.data.resp);
const userData = parsedData.data;
setLoginResponse({
Token: userData.token,
UserID: userData.user.id,
UserName: userData.user.userName,
firstName: userData.user.firstName,
rcCode: userData.user.attributes.rcCode
});
}
In the .then
setLoginResponse({...loginResponse, Token: response.data.resp.data.token, UserId: response.data.resp.data.user.id, ...}
You can destructure your response object first and store values in variables to make the setLoginResponse more easy to read.
https://reactjs.org/docs/hooks-state.html

Filter JSON object array on multiple values or arguments javascript

users = [
{
"username": "Alice",
"firstName": "Alice-U",
"lastName": "Wonderland"
},
{
"username": "bob",
"firstName": "Bob-u",
"lastName": "Builder",
},
{
"username": "charly",
"firstName": "Charly-u",
"lastName": "Brown",
}
]
I want to be able to filter this array on multiple values like:
Search Criteria: { "username" : "Alice" } should return:
{
"username": "Alice",
"firstName": "Alice-U",
"lastName": "Wonderland"
}
Similary for: { "username" : "charly", "firstName": "Charly-u" } should return :
{
"username": "charly",
"firstName": "Charly-u",
"lastName": "Brown",
}
with exact string matching using javaScript or jQuery.
You can employ .every to check that each of the criteria keys matches:
function filterBy(list, criteria) {
return list.filter(candidate =>
Object.keys(criteria).every(key =>
candidate[key] == criteria[key]
)
);
}
let users = [
{ "username": "Alice", "firstName": "Alice-U", "lastName": "Wonderland" },
{ "username": "bob", "firstName": "Bob-u", "lastName": "Builder" },
{ "username": "charly", "firstName": "Charly-u", "lastName": "Brown" }
];
console.log(filterBy(users, { "username" : "Alice" }));
console.log(filterBy(users, { "username" : "charly", "firstName": "Charly-u" }));
Why not Array.prototype.filter()? to filter only the element that has username="Alice". By the way you can add multiple object keys inside your filter's arrow function while filtering array of object. For example:
user.username ==='Charly' && firstName==='Charly-u'
users = [{
"username": "Alice",
"firstName": "Alice-U",
"lastName": "Wonderland"
},
{
"username": "bob",
"firstName": "Bob-u",
"lastName": "Builder",
},
{
"username": "charly",
"firstName": "Charly-u",
"lastName": "Brown",
}
];
result = users.filter(user => user.username ==='Alice');
console.log(result);
can’t it be just a function with for loop?
//call
this.filterIt( ‘username’ , ‘Alice’, users);
//function
Function filterIt (key, value, arr){
result = [];
for ( a in arr){
if (a[key] == value) result.push(a);
}
return result;
}
You can write it in the following way. If you want to do exact search write a search function like this:
function search(term) {
return users.filter(({username, firstName, lastName}) => {
return username.toLowerCase() === term.toLowerCase() ||
firstName.toLowerCase() === term.toLowerCase() ||
lastName.toLowerCase() === term.toLowerCase()
})
}
Instead of comparing each key one can iterate all object properties using object.keys.
If you want to match each anything use following function
function search(term) {
return users.filter(({username, firstName, lastName}) => {
return username.toLowerCase().indexOf(term.toLowerCase()) > -1 ||
firstName.toLowerCase().indexOf(term.toLowerCase()) > -1 ||
lastName.toLowerCase().indexOf(term.toLowerCase()) > -1
})
}
This will even match searchTerm anywhere. Like if you use this as search('al'). It will return the first object, whereas the first function will need exact string like search('alice') to work.
const users = [{
"username": "Alice",
"firstName": "Alice-U",
"lastName": "Wonderland"
},
{
"username": "bob",
"firstName": "Bob-u",
"lastName": "Builder",
},
{
"username": "charly",
"firstName": "Charly-u",
"lastName": "Brown",
}
]
function searchFull(term) {
return users.filter(({
username,
firstName,
lastName
}) => {
return username.toLowerCase() === term.toLowerCase() ||
firstName.toLowerCase() === term.toLowerCase() ||
lastName.toLowerCase() === term.toLowerCase()
})
}
function search(term) {
return users.filter(({
username,
firstName,
lastName
}) => {
return username.toLowerCase().indexOf(term.toLowerCase()) > -1 ||
firstName.toLowerCase().indexOf(term.toLowerCase()) > -1 ||
lastName.toLowerCase().indexOf(term.toLowerCase()) > -1
})
}
console.log(searchFull('alice'))
console.log(search('al'))

JSON data concatenate two data [duplicate]

This question already has an answer here:
How to concatenate two string fields into one in a JavaScript array? [closed]
(1 answer)
Closed 4 months ago.
In Javascript, How can I convert this JSON Data?
I need to concatenate the firstname and lastname into its fullname
Data
[
{
"lastname": "Stark",
"firstname": "Tony",
"id": 1
},
{
"lastname": "Parker",
"firstname": "Peter",
"id": 2
},
{
"lastname": "Rogers",
"firstname": "Steve",
"id": 3
},
]
This should be the result:
Result
[
{
"fullname": "Tony Stark",
"id": 1
},
{
"fullname": "Peter Parker",
"id": 1
},
{
"fullname": "Steve Rogers",
"id": 1
},
]
Use JSON.parse to parse your data into JavaScript object and then with Array#map function iterate over the items and populate your custom objects.
const dataAsJson = `[
{
"lastname": "Stark",
"firstname": "Tony",
"id": 1
},
{
"lastname": "Parker",
"firstname": "Peter",
"id": 2
},
{
"lastname": "Rogers",
"firstname": "Steve",
"id": 3
}
]`;
const data = JSON.parse(dataAsJson);
const changedData = data.map(item => ({ fullname: `${item.firstname} ${item.lastname}`, id: item.id }));
console.log(changedData);
If this data is available to your script as a JSON string, then you can use JSON.parse() to obtain the array of objects.
Then do whatever you want with that array of objects.
Then, eventually, convert the resulting data back to a string using JSON.stringify().
You can also use array#reduce.
const data = `[{"lastname": "Stark","firstname": "Tony","id": 1},{"lastname": "Parker","firstname": "Peter","id": 2},{"lastname": "Rogers","firstname": "Steve","id": 3}]`;
var result = JSON.parse(data).reduce((arr, obj) => {
return arr.push({fullName : obj.firstname + " " + obj.lastname, id: obj.id }), arr;
},[]);
console.log(result);
First, parse the string to get the data in JSON by using
JSON.parse()
. If you're using es6, use this:
const newArray = JSON.parse(yourArray).map((user) => ({
fullName: `${user.firstname} ${user.lastname}`,
id: user.id
}));
otherwise use this:
const newArray = yourArray.map(function (user) {
return {
fullName: user.firstname + user.lastname,
id: user.id
};
});
Thanks.
Logically all you need to do is loop through the array and make a new object with the firstname and lastname contacted. So here is a non-fancy ES5 way to do this:
// JSON Data parsed into JS Object
var arr = JSON.parse('[{"lastname":"Stark","firstname":"Tony","id":1},{"lastname":"Parker","firstname":"Peter","id":2},{"lastname":"Rogers","firstname":"Steve","id":3}]');
var newArr = [];
for(var i=0; i<arr.length; i++)
newArr.push({"fullname": arr[i]["firstname"] + " " + arr[i]["lastname"], "id": arr[i]["id"]});
console.log(JSON.stringify(newArr)); // Convert to text for JSON.

NodeJs: Data Transformers like in Laravel PHP Framework

I've created multiple REST API projects using the Laravel framework and basing my code structure on the Laracasts tutorial. However we are deciding to move some projects using NodeJs as a backend. I'm beginning to learn node and I'm trying to replicate it in Node. I was able to do it for a singe object response but for multiple objects I can't seem to make it work.
Here is my controller:
index(req,res) {
User
.findAll()
.then(function(users){
res.json(api.respond(transfomer.transformCollection(users)));
})
.catch(function(error){
res.json(api.respondWithError('users not found',error));
});
}
api controller:
module.exports = {
// response w/o error
respond: function(data,msg,status) {
if (msg == null) {
return {
'status': status || true,
'data': data
};
} else {
return {
'status': true,
'message': msg,
'data': data
};
}
},
// response with error
respondWithError: function(msg,error) {
var self = this;
var status = false;
var data = {
'error': error
};
return this.respond(data,msg,status);
},
};
transformer.js
module.exports = {
// single transformation
transform (user) {
return {
'id' : user.id,
'username': user.username,
'firstname': user.firstname,
'lastname': user.lastname,
'address': user.address,
'phone': user.phone,
'mobile': user.mobile,
'status': user.status
};
},
//
transformCollection(users) {
var self = this;
var data = [];
for (var i = 0; i <= users.length; i++) {
data.push(this.transform(users[i]));
}
return data;
}
};
sample output
{
"status": true,
"data": [
{
"id": 1,
"username": "b#email.com",
"firstname": "Jon",
"lastname": "Doe",
"address": "Homes",
"phone": "+966501212121",
"mobile": "+966501212121",
"status": "NOT VERIFIED"
},
{
"id": 1,
"username": "b#email.com",
"firstname": "Jon",
"lastname": "Doe",
"address": "Homes",
"phone": "+966501212121",
"mobile": "+966501212121",
"status": "NOT VERIFIED"
},
{
"id": 1,
"username": "b#email.com",
"firstname": "Jon",
"lastname": "Doe",
"address": "Homes",
"phone": "+966501212121",
"mobile": "+966501212121",
"status": "NOT VERIFIED"
},
{
"id": 1,
"username": "b#email.com",
"firstname": "Jon",
"lastname": "Doe",
"address": "Homes",
"phone": "+966501212121",
"mobile": "+966501212121",
"status": "NOT VERIFIED"
},
]
}
Sorry for asking this as I'm a bit newb with node. Is it possible to achieve that output as I tried different ways but Im still getting errors. Btw I'm using sequelize for the database.
Thanks.
You can use this:
const options = {
raw: true,
attributes: ['id', 'name', 'code', 'createdAt','updatedAt']
};
country.findAndCountAll(options).then(querySnapshot => {
const total = querySnapshot.count;
resolve({
docs: querySnapshot.rows,
total: total
})
}).catch((err) => {
reject(err)
});
I've found the answer to my question since sequelize is returning the results as an object with additional properties aside from the database results I had to modify the controller to set and convert the results to raw in order for me to get the array of objects from the query results from the database.
index(req,res) {
User
.findAll({ raw: true }) // added "raw: true"
.then(function(users){
res.json(api.respond(transfomer.transformCollection(users)));
})
.catch(function(error){
res.json(api.respondWithError('users not found',error));
});
},
This will return the array of objects from the database and from there the data transformer is working properly. Thank you for all the help.

Categories

Resources