Javascript get values from multidimensional array object by other values - javascript

I have a structure like below;
var devices = {
'device-1' : {
'id' :'device1',
'template' :'template-1',
'user-1' :{
'name' : 'John Doe',
'authority' : 'author1',
},
'admin-1' :{
'name' : 'Bob Doe',
'authority' : 'author2',
},
'user-35' :{
'name' : 'Bill Doe',
'authority' : 'author1',
},
'author-42' :{
'name' : 'Jack Doe',
'authority' : 'author1|author3',
}
},
'device-2' : {
'id' :'device2',
'template' :'template-2',
'some-27' :{
'name' : 'John Doe',
'authority' : 'author1',
},
'other-42' :{
'name' : 'Jack Doe',
'authority' : 'author2',
}
},
'device-7' : {
'id' :'device7',
'template' :'template-1',
'user-2' :{
'name' : 'Samantha Doe',
'authority' : 'author2',
}
'admin-40' :{
'name' : 'Marry Doe',
'authority' : 'author1',
},
}
};
and I would like to get all 'value' entries of user-x elements by filtering their 'property' values.
Eg.
I would like filter all 'name's of users (no matter in which device and what are those user-ids) based on their 'authority' property and get 'John Doe','Bill Doe','Jack Doe','Marry Doe' (as an array) if I would like filter for 'author1' 'authority' so I can get which users have 'author1' authorities on any devices.
I've checked many places (including StackOverflow) but most of the examples are limited to two-dimensional object arrays, variables were specific or objects were based on an integer (like [0] => Array).
But in this example, 'device-x' and 'user-x' entries are uncertain (so I cannot say their values are these) but 'name' and 'authority' keys are certain (assign by the system) and the count of these variables can be varied (crud operations).
Thanks right now.
UPDATE : Because of my assumption error (I thought that if I write user-x parts different that each other, people think that these values are not follow any rule) question was not clear. So I edited in code.
Finally : owners of 'name' and 'authority' key-value pairs are user names and they are user defined.
So, all device objects will have id, template, unknown-user-field, but all unknown-user-fields must have 'name' and 'authority' key-value pairs.

Using reduce & filter & map.
Updated: I've added a isLikeUserObj function that probs for name & authority fields.
const devices = {
'device-1': {
'id': 'device1',
'template': 'template-1',
'user-1': {
'name': 'John Doe',
'authority': 'author1',
},
'admin-1': {
'name': 'Bob Doe',
'authority': 'author2',
},
'user-35': {
'name': 'Bill Doe',
'authority': 'author1',
},
'author-42': {
'name': 'Jack Doe',
'authority': 'author1|author3',
}
},
'device-2': {
'id': 'device2',
'template': 'template-2',
'some-27': {
'name': 'John Doe',
'authority': 'author1',
},
'other-42': {
'name': 'Jack Doe',
'authority': 'author2',
}
},
'device-7': {
'id': 'device7',
'template': 'template-1',
'user-2': {
'name': 'Samantha Doe',
'authority': 'author2',
},
'admin-40': {
'name': 'Marry Doe',
'authority': 'author1',
},
}
};
const result = getUserByAuthority('author3');
function getUserByAuthority(requiredAuth) {
return Object.keys(devices).reduce((result, deviceKey) => {
const users = Object.keys(devices[deviceKey])
.filter((key) => isUserLikeObj(devices[deviceKey][key]))
.map(userKey => devices[deviceKey][userKey])
.filter((user) => user.authority.split('|').indexOf(requiredAuth) > -1)
.map((user) => user.name)
return result.concat(users);
}, [])
}
function isUserLikeObj(value) {
return typeof value === 'object' && value.hasOwnProperty('name') && value.hasOwnProperty('authority')
}
console.log(result)

You can use for-in loop to traverse an object. Following ways could achieve your need
const result = []
for (let i in devices) {
for (let j in devices[i]) {
if (/user-\d+/.test(j)) {
if (devices[i][j].authority.split('|').indexOf('author1') !== -1) {
result.push(devices[i][j].name)
}
}
}
}
console.log(result)

Related

Javascript sort array of objects alphabetically AND put first objects with value

I'm trying to sort this data which contains various arrays of objects, the console.log of myData is something like:
[
{
name: 'Cdb',
image: 'xxx',
coll: 'xxx'
},
{
name: 'Bcd',
image: 'xxx',
coll: 'xxx',
url: 'myurl'
}
]
[
{
name: 'Abc',
image: 'xxx',
coll: 'xxx'
}
]
I'm trying to sort it alphabetically (based on value of name) and if the object has the parameter url , put it at the beginning.
So the output would be:
name: 'Cdb',
image: 'xxx',
coll: 'xxx',
url: 'myurl'
name: 'Abc',
image: 'xxx',
coll: 'xxx'
name: 'Bcd',
image: 'xxx',
coll: 'xxx'
what I tried is this, and many variations of it, but it doesn't work:
var myData = props?.data
console.log(props?.data)
if(props.data){
// those with url first, then alphabetically
myData = props.data.sort(function(a, b){
return b.url? 1 || (a.name < b.name) : -1;
})
}
You can use !url as a number (0 or 1) and subtract them:
const arr = [{"name":"Cdb","image":"xxx","coll":"xxx"},{"name":"Bcd","image":"xxx","coll":"xxx","url":"myurl"},{"name":"Abc","image":"xxx","coll":"xxx"}]
arr.sort((a, b) => !a.url - !b.url || a.name.localeCompare(b.name));
console.log(arr)
This is saying that if exactly one of both has the url argument, that one should come first. Otherwise (if both have it, or neither have it) then the name is decisive.
This way, when multiple objects have the url argument, they will also be ordered among themselves by name.

JSON logic Checking best approach

I have a search form and more than 15 fields for searching. I have to call different API's based on the search Parameters
For instance below is my request Params
requestParams = {
firstName : 'Jack',
lastName : 'Jill',
dob : '12-10-2020',
email : '',
phone : '',
address: '',
postCode: '',
customerID : '11111111',
status : 'Active'
}
Currently am using if conditions to achieve this
if( checkNull(requestParams.firstName) && checkNull(requestParams.lastName) ) {
callApiOne();
}
if( checkNull(requestParams.customerID)) {
callApiTwo();
}
if( checkNull(requestParams.firstName) && checkNull(requestParams.status) ) {
callApiOne();
}
if( checkNull(requestParams.firstName) && checkNull(requestParams.phone) ) {
callApiTwo();
}
My search combination list may increase up to 25 what is the best approach to keep it configurable and reusable.
Based on the input you have given. I came up with the solution.
Given your request param
const requestParams = {
firstName : 'Jack',
lastName : 'Jill',
dob : '12-10-2020',
email : '',
phone : '',
address: '',
postCode: '',
customerID : '11111111',
status : 'Active',
};
First create a variable containing all the fields you need which contains the key of your request param and the api based on that.
const PARAMS = [
{ key: 'lastName', api: 'apiOne' },
{ key: 'dob', api: 'apiTwo' },
{ key: 'email', api: 'apiThree' },
{ key: 'phone', api: 'apiFour' },
{ key: 'address', api: 'apiFive' },
{ key: 'postCode', api: 'apiSix' },
{ key: 'customerID', api: 'apiSeven' },
{ key: 'status', api: 'apiOne' },
];
Then loop through each items from above list and check if requestParams contains a value and if its not null. For some like customerID you can have a exception.
PARAMS.forEach(({ key, api }) => {
if (key === 'customerID' && checkNull(requestParams.customerID)) {
callApi(api);
return;
}
if (checkNull(requestParams.firstName) && checkNull(requestParams[key])) {
callApi(api);
}
});
If you post your full code I can help you better.

Check if the User Id stored in an object in an array is equal to the Id of the Authenticated user

Here's the structure of the array:
post: [
comments: {
userId: 123123123,
name: John doe
}
]
I want to check if the authenticated user's Id (auth.user.id) exists in any of the the comments stored in the Post array. I want to return a boolean as a result.
I have tried using the find() method and the includes() method but haven't had success.
posts.filter(comments => comments.userId === auth.user.id).length !== 0
this expression will evaluate to true if the user id exists in the posts comments , and evaluate to false otherwise
post: [
comments: {
userId: 123123123,
name: John doe
}
]
its not valid.
it should be this
post : [{
comments : {
userId: 123123123,
name: 'John doe'
}
}]
or this
post: [
{
userId: 123123123,
name: John doe
}
]
var post = [{
comments : {
userId: 123123123,
name: 'John doe'
}
}]
console.log(post);
var f = userId => post.some(x => x.comments.userId == userId);
console.log(f(123123123))

Javascript object : select the whole object that has known key : value pair

I'm confused with a complex json object, in the example bellow, how can I store in a variable the whole object that has entreprise : 'microsoft'.
clientList = {
id-1111 : {
entreprise : 'facebook',
president : 'Mark',
},
id-2222 : {
entreprise : 'microsoft',
president : 'Bill',
},
id-3333 : {
entreprise : 'apple',
president : 'Tim'
}
}
I dynamicly get, for axample, 'Microsoft', and I would like to obtain as output :
{
entreprise : 'microsoft',
president : 'Bill'
}
I know it is a basic question, but I'm struggling with that for hours.
Thanks for your help.
You can use find to find a single item from a list.
var clientList = {
"id-1111": {
entreprise : 'facebook',
president : 'Mark',
},
"id-2222" : {
entreprise : 'microsoft',
president : 'Bill',
},
"id-3333" : {
entreprise : 'apple',
president : 'Tim'
}
};
var result = Object.values(clientList).find(x => x.entreprise == "microsoft");
console.log(result);
To find all objects with a paticular enterprise, use Array.filter:
const clientList = {
"id-1111" : {
entreprise : 'facebook',
president : 'Mark',
},
"id-2222" : {
entreprise : 'microsoft',
president : 'Bill',
},
"id-3333" : {
entreprise : 'apple',
president : 'Tim'
}
};
function findClientsByEnterprise(enterprise) {
return Object.values(clientList).filter( i => i.entreprise === enterprise);
}
console.log(findClientsByEnterprise("microsoft"))
Your object has broken. Use quote in your object key.
clientList = {
'id-1111' : {
entreprise : 'facebook',
president : 'Mark',
},
'id-2222' : {
entreprise : 'microsoft',
president : 'Bill',
},
'id-3333' : {
entreprise : 'apple',
president : 'Tim'
}
};
function objectSearch(key, value,obj){
for(o in obj){
if(obj[o][key] == value){
return obj[o];
}
}
return {};
}
console.log(objectSearch('entreprise','microsoft',clientList));
if the enterprise can be used as a unique ID, you could just use it as such:
'microsft': {
enterprise: 'microsoft',
president: 'Bill'
}
but as a general rule, it is not a great practice to do this. So maintaining a structure with a list of objects with unique ID's and using find would be the best solution and best practice:
clientList = [
{
id: 'id-1111',
entreprise : 'facebook',
president : 'Mark',
},
{
id: 'id-2222',
entreprise : 'microsoft',
president : 'Bill',
},
{
id: 'id-3333',
entreprise : 'apple',
president : 'Tim'
}
}
const result = clientList.find(clientObj => clientObj.enterprise === "microsoft");

How to create dynamic table headers from JSON in React?

I have a JSON array of objects, I want to create a dynamic table columns/headers based on it in React.
The data:
example = [
{
id: 0,
city: 'New York',
},
{
id: 1,
city: 'Paris',
},
]
I want to iterate through the array, get the key and add extra fields.
So far I have:
columns() {
return Object.keys(Example[0]).map((key) => {
return {
cityName: key,
capital: false,
};
});
}
I get the keys, but they are unordered (random) and the extra field is added to all the objects. I want to get each key to use it as table header (column name) and be able to change capital for each object.
How can I do that in React?
You can use Array.map for this.
example = [
{
id: 0,
city: 'New York',
},
{
id: 1,
city: 'Paris',
},
];
example.map((obj) => {
return {
CITY : obj.city,
ID : obj.id
// Do whatever with the objects
}
})
arr => arr && arr[0] ? object.keys(arr[0]) : [];
make sure all items in array have same keys

Categories

Resources