Get value from a JavaScript array.object using id number - javascript

Based on the var data below. How can I get the full_name value if all I have is the number 2? Number 2 corresponds with id: 2 and the full_name would be Eric
var data = [{
id: 0,
full_name: 'None',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 1,
full_name: 'John',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 2,
full_name: 'Eric',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 3,
full_name: 'Larry',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 4,
full_name: 'Rick',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 5,
full_name: 'John',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 6,
full_name: 'Eric',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 7,
full_name: 'Larry',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 8,
full_name: 'Rick',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 9,
full_name: 'John',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 10,
full_name: 'Eric',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 11,
full_name: 'Larry',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}, {
id: 12,
full_name: 'Rick',
gravatar_url: 'http://gravatar.com/avatar/31b64e4876d603ce78e04102c67d6144?s=80'
}];

(data.filter(function(x) { return x.id == 2 })[0] || {}).full_name;
// => "Eric"
data.filter will return only elements that fit the given criterion; in this case, id being 2. Since we only care about one element, we will just take the first found element; but if none exist, .full_name will give an error about full_name not being defined on undefined, so we put in an empty object just in case the search fails using || {}.

Amadan's answer most probably is better/more failure proof than mine, but if you know that your array of objects will always contain objects from Id 0 to Id infinite, you could also get it with
var wanted = data[number].fullName

ES6 offers Array#find, to find the first element in an array that meets some condition:
var wanted = data.find(elt => elt.id === 2);
If you don't have this available, there are various polyfills, including one on the page referenced above.

function myQuery(array, id){
for(i in array){
if(array[i].id === id){
console.log(data[i].full_name);
return data[i].full_name;
}
}
}
myQuery(data, 2)
If you are keeping your ID equal to the place in the array, you could just do this.
function myQuery(id){
return array[id].full_name
}

Related

Build nested object array from recursive function

How would i utilize my getChildren() function to create a larger function which takes my two main arrays objs and objRefs and outputs a single array of objs demonstrating their parent/child relationship.
here are the two main data arrays
const objs = [
{ name: "Kevin", age: 5, id: 1 },
{ name: "Matt", age: 53, id: 5 },
{ name: "Marry", age: 30, id: 2 },
{ name: "Leslie", age: 21, id: 3 },
{ name: "Sarah", age: 46, id: 4 },
{ name: "Heather", age: 37, id: 6 },
{ name: "Cory", age: 19, id: 7 },
]
const objRefs = [
{ parent_id: 5, obj_id: 7 }, // cory child of matt
{ parent_id: null, obj_id: 6 }, // matt root
{ parent_id: null, obj_id: 4 }, // sarah root
{ parent_id: null, obj_id: 5 }, // heather root
{ parent_id: 5, obj_id: 3 }, // leslie child of matt
{ parent_id: 4, obj_id: 2 }, // mary child of sarah
{ parent_id: 3, obj_id: 1 }, // kevin child of leslie
]
My goal is to run a function called getFamilyTree() which would return me this...
const tree = [
{
id: 5,
name: "Matt",
age: 53,
children:[
{
id: 3,
name: "Leslie",
age: 21,
children:[
{
id: 1,
name: "Kevin",
age: 5,
children:[ ]
}
]
},
{
id: 7,
name: "Cory",
age: 19,
children:[ ]
}
]
},
{
id: 6,
name: "Heather",
age: 37,
children:[ ]
},
{
id: 4,
name: "Sarah",
age: 46,
children:[
{
id: 2,
name: "Marry",
age: 30,
children:[ ]
}
]
}
]
I have a function that returns me all the children for the given parent node id, but im not sure how structure a function to return me the entire tree like my example.
function getChildren(parent_id) {
let children = []
for (var i = 0; i < objRefs.length; i++) {
const ref = objRefs[i]
if (ref.parent_id === parent_id) {
const obj = objs.find(obj => {
return obj.id === ref.obj_id
})
children.push(obj)
}
}
return children
}
function getFamilyTree() {
let result = []
... // build recursive family tree
return result
}
You don't need a recursive function to construct that.
To get a reasonable time complexity, store all the objs to a Map or something (if the ids are sequential, even an array will work) keyed by id. Then, just iterate over objRefs and construct the relations appropriately:
const objs = [
{ name: "Kevin", age: 5, id: 1 },
{ name: "Matt", age: 53, id: 5 },
{ name: "Marry", age: 30, id: 2 },
{ name: "Leslie", age: 21, id: 3 },
{ name: "Sarah", age: 46, id: 4 },
{ name: "Heather", age: 37, id: 6 },
{ name: "Cory", age: 19, id: 7
},
]
const objRefs = [
{ parent_id: 5, obj_id: 7 }, // cory child of matt
{ parent_id: null, obj_id: 6 }, // matt root
{ parent_id: null, obj_id: 4 }, // sarah root
{ parent_id: null, obj_id: 5 }, // heather root
{ parent_id: 5, obj_id: 3 }, // leslie child of matt
{ parent_id: 4, obj_id: 2 }, // mary child of sarah
{ parent_id: 3, obj_id: 1 }, // kevin child of leslie
]
function getFamilyTree(objs, objRefs){
const tree = []
const map = new Map(
objs.map(e => [e.id, { ...e, children: [] }])
)
for(const {parent_id, obj_id} of objRefs){
if(parent_id === null){
tree.push(map.get(obj_id))
}else{
map.get(parent_id).children.push(map.get(obj_id))
}
}
return tree
}
const tree = getFamilyTree(objs, objRefs)
console.log(tree)
I don't think you even need the getChildren function to actually build your tree. Using Maps instead could be useful:
const objs = [
{ name: "Kevin", age: 5, id: 1 },
{ name: "Matt", age: 53, id: 5 },
{ name: "Marry", age: 30, id: 2 },
{ name: "Leslie", age: 21, id: 3 },
{ name: "Sarah", age: 46, id: 4 },
{ name: "Heather", age: 37, id: 6 },
{ name: "Cory", age: 19, id: 7 },
]
const objRefs = [
{ parent_id: 5, obj_id: 7 }, // cory child of matt
{ parent_id: null, obj_id: 6 }, // matt root
{ parent_id: null, obj_id: 4 }, // sarah root
{ parent_id: null, obj_id: 5 }, // heather root
{ parent_id: 5, obj_id: 3 }, // leslie child of matt
{ parent_id: 4, obj_id: 2 }, // mary child of sarah
{ parent_id: 3, obj_id: 1 }, // kevin child of leslie
]
function getFamillyTree(){
const nodes = new Map()
// Preparing the data nodes
objs.forEach(elt => nodes.set(elt.id, {...elt, children: [], root: false}))
// Linking the nodes to make the parent <-> children relations
objRefs.filter(rel => !!rel.parent_id).forEach(rel => {
const parent = nodes.get(rel.parent_id)
parent.children.push(nodes.get(rel.obj_id))
})
// Marking the roots
objRefs.filter(rel => rel.parent_id === null).forEach(rel => {
const obj = nodes.get(rel.obj_id)
obj.root = true
})
return Array.from(nodes.values()).filter(obj => obj.root)
}
document.write(JSON.stringify(getFamillyTree(), null, 4))
Edit: This answer can be slightly off, because as Nina stated in a comment on the question, OP seems to ask for an explicitly recursive solution, leaving this here for reference.
You could use some object as reference to the persons and their relations and map the nodes with their children.
const
getChildren = parent => (references[parent] || []).map(id => ({
...nodes[id],
children: getChildren(id)
})),
people = [{ name: "Kevin", age: 5, id: 1 }, { name: "Matt", age: 53, id: 5 }, { name: "Marry", age: 30, id: 2 }, { name: "Leslie", age: 21, id: 3 }, { name: "Sarah", age: 46, id: 4 }, { name: "Heather", age: 37, id: 6 }, { name: "Cory", age: 19, id: 7 }],
children = [{ parent_id: 5, obj_id: 7 }, { parent_id: null, obj_id: 6 }, { parent_id: null, obj_id: 4 }, { parent_id: null, obj_id: 5 }, { parent_id: 5, obj_id: 3 }, { parent_id: 4, obj_id: 2 }, { parent_id: 3, obj_id: 1 }],
nodes = Object.fromEntries(people.map(o => [o.id, o])),
references = children.reduce((r, { parent_id, obj_id }) => ((r[parent_id] ??= []).push(obj_id), r), {}),
tree = getChildren(null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
An approach with a single loop of children.
const
getTree = (people, children, root) => {
const
nodes = Object.fromEntries(people.map(o => [o.id, o])),
t = {};
children.forEach(({ parent_id: p, obj_id: id }) =>
((t[p] ??= {}).children ??= []).push(Object.assign(t[id] ??= {}, nodes[id]))
);
return t[root].children;
},
people = [{ name: "Kevin", age: 5, id: 1 }, { name: "Matt", age: 53, id: 5 }, { name: "Marry", age: 30, id: 2 }, { name: "Leslie", age: 21, id: 3 }, { name: "Sarah", age: 46, id: 4 }, { name: "Heather", age: 37, id: 6 }, { name: "Cory", age: 19, id: 7 }],
children = [{ parent_id: 5, obj_id: 7 }, { parent_id: null, obj_id: 6 }, { parent_id: null, obj_id: 4 }, { parent_id: null, obj_id: 5 }, { parent_id: 5, obj_id: 3 }, { parent_id: 4, obj_id: 2 }, { parent_id: 3, obj_id: 1 }],
tree = getTree(people, children, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Calculate percentile rank using javascript for each user in array of json objects based on user's overall place

Using javascript, how can I calculate the percentile rank for each participant in a results list where person with place = 1 (Joe) has a 100% rank since they won a race, for instance, but then all other people's ranks are lower from there? Here are some sample results. Can someone please help?
const results = [{
name: 'joe',
place: 1,
rank: '100%'
}, {
name: 'roger',
place: 2,
rank: '?'
}, {
name: 'heather',
place: 3,
rank: '?'
}, {
name: 'craig',
place: 4,
rank: '?'
}, {
name: 'sally',
place: 5,
rank: '?'
}, {
name: 'cory',
place: 6,
rank: '?'
}, {
name: 'joel',
place: 7,
rank: '?'
}];
You can subtract one less than each person's rank from the number of people and divide by the number of people to get the percentage rank.
const results = [{
name: 'joe',
place: 1,
rank: '?'
}, {
name: 'roger',
place: 2,
rank: '?'
}, {
name: 'heather',
place: 3,
rank: '?'
}, {
name: 'craig',
place: 4,
rank: '?'
}, {
name: 'sally',
place: 5,
rank: '?'
}, {
name: 'cory',
place: 6,
rank: '?'
}, {
name: 'joel',
place: 7,
rank: '?'
}];
results
.forEach(person=>person.rank
= (+((results.length - person.place + 1) / results.length * 100).toFixed(2)) + '%');
console.log(results);

How to add object element in array based on condition

I have static array constant of objects something similar to below.
export const EMPLOYEES = [
{
id: 2,
name: ‘John’,
},
{
id: 3,
name: ‘Doe’,
},
{
id: 4,
name: ‘Bull’,
},
{
id: 5,
name: ‘Scott’,
},
];
Now I need to add the last element only based on if some condition is true. Some this like if isAmerican() is true.
Can somebody help me here how to add element based on the condition? Thanks.
You can do it using spread operator:
export const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "Jemmy"}] : []
];
You should never modify (or try to modify) a constant. I can see two ways you can do this:
Create a pure function to return a new constant with the new object added to the array
Use a spread operator in the definition of the constant
Option 1: Pure function
function makeNewArray(array, objectToAppend, isAmerican) {
return isAmerican ? [...array, objectToAppend] : array
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
}
];
const arrayWithAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "American Frank"}, true);
const arrayWithoutAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "Not American Frank"}, false);
console.log(arrayWithAmerican);
console.log(arrayWithoutAmerican);
Option 2: Spread operator
function isAmerican(){
// generic code here.
return true;
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "American Frank"}] : []
];
If the condition will be fulfilled, simply push an object to your EMPLOYEES array:
let isAmerican = true;
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
];
if(isAmerican) {
EMPLOYEES.push({
id: 6,
name: "Frank"
})
}
console.log(EMPLOYEES)
Fiddle: https://jsfiddle.net/rqx35pLz/

Sort a flat list by parent id with lodash

I have a JSON list of objects with an id, name and reference to parent id :
const myList = [
{
id: 1,
name: "name1",
parentId: null
},
{
id: 5,
name: "name5",
parentId: 32
},
{
id: 32,
name: "name32",
parentId: 48
},
{
id: 48,
name: "name48",
parentId: 1
}
]
I would like to sort that list hierarchically, depending on the parent id :
[
{
id: 1,
name: "name1",
parentId: null
},
{
id: 48,
name: "name48",
parentId: 1
},
{
id: 32,
name: "name32",
parentId: 48
},
{
id: 5,
name: "name5",
parentId: 32
}
]
I'm new in Javascript programming and lodash, and I was wondering if there is an easy way to sort that list with lodash ?
Thank you in advance.
Benj
I found a solution with lodash.
Not sure it's the best but it works.
var parentId = null;
var sortedList = [];
var byParentsIdsList = _.groupBy(myList, "parentId"); // Create a new array with objects indexed by parentId
while (byParentsIdsList[parentId]) {
sortedList.push(byParentsIdsList[parentId][0]);
parentId = byParentsIdsList[parentId][0].id;
}
You can use lodash's method sortBy
var sorted = _.sortBy(myList, "parentId");
console.log(sorted);
/* OUTPUT
[
{
id: 1,
name: "name1",
parentId: null
},
{
id: 48,
name: "name48",
parentId: 1
},
{
id: 5,
name: "name5",
parentId: 32
},
{
id: 32,
name: "name32",
parentId: 48
}
]
*/
https://jsfiddle.net/L88t09ne/
with vanilla js [].sort() method:
const myList = [
{
id: 1,
name: "name1",
parentId: null
},
{
id: 5,
name: "name5",
parentId: 32
},
{
id: 32,
name: "name32",
parentId: 48
},
{
id: 48,
name: "name48",
parentId: 1
}
];
var arr = myList.sort(function(a,b){
return a.parentId -b.parentId
});
console.log(arr)

Expand/Collapse all the gof kendoTreeList

I am using kendoTreeList
and I am trying to expand all the groups. Here is my code sample
But it seems like the kendoTreeList support only expanding the first group. I tried the following selector in the expand method as well.
treeList.expand($(".k-treelist-group")); to expand all the groups. Even though the selector $(".k-treelist-group").length is 3 (total number of groups) but the treelist only expand the first group.
Any suggestion please let me know.
You are right, according with the information on their site it expands the row and not the rows.
Then you can iterate for getting the same effect:
var treeList = $("#treeList").data("kendoTreeList");
var rows = $("tr.k-treelist-group", treeList.tbody);
$.each(rows, function(idx, row) {
treeList.expand(row);
});
$(document).ready(function() {
$("#treeList").kendoTreeList({
columns: [ "id", "name" ],
loadOnDemand:false,
dataSource: [
{ id: 1, parentId: null, name: "Group", age: 30 },
{ id: 2, parentId: 1, name: "John Doe", age: 33 },
{ id: 3, parentId: 1, name: "Johson", age: 33 },
{ id: 4, parentId: null, name: "Group 2", age: 30 },
{ id: 5, parentId: 4, name: "Doe ", age: 33 },
{ id: 6, parentId: 4, name: "Noomi", age: 33 },
{ id: 7, parentId: null, name: "Group 3", age: 30 },
{ id:8, parentId: 7, name: "Doe ", age: 33 },
{ id: 9, parentId: 7, name: "Noomi", age: 33 }
]
});
var treeList = $("#treeList").data("kendoTreeList");
var rows = $("tr.k-treelist-group", treeList.tbody);
$.each(rows, function(idx, row) {
treeList.expand(row);
});
});
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.default.min.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.3.1119/js/kendo.all.min.js"></script>
<div id="treeList"></div>
If you expand many rows you can get into some performance issues, then one alternative to looping the .expand method is to modify the data and bind it again.
var treeList = $("#treeList").data("kendoTreeList");
var dataItems = treeList.dataSource.data();
$.each(dataItems, function(i, item) {
item.expanded = true;
});
treeList.dataSource.data(dataItems);
You can also modify the data before it's bound.
dataSource: {
data: [
{ id: 1, parentId: null, name: "Group", age: 30 },
{ id: 2, parentId: 1, name: "John Doe", age: 33 },
{ id: 3, parentId: 1, name: "Johson", age: 33 },
{ id: 4, parentId: null, name: "Group 2", age: 30 },
{ id: 5, parentId: 4, name: "Doe ", age: 33 },
{ id: 6, parentId: 4, name: "Noomi", age: 33 },
{ id: 7, parentId: null, name: "Group 3", age: 30 },
{ id:8, parentId: 7, name: "Doe ", age: 33 },
{ id: 9, parentId: 7, name: "Noomi", age: 33 }
],
schema: {
parse: function(data) {
$.each(data, function(i, item) {
item.expanded = true;
});
return data;
}
}
}

Categories

Resources