Getting syntax error when trying to create dictionary of object - javascript

I am getting an array of objects from API like below :
[
{
jobId:100,
jobName: "Java",
cities:[
{
cityId:10,
name : "chicago"
},
{
statusId:11,
name : "miami"
}]
},
{
jobId:101,
jobName: "Python",
cities:[
{
cityId:11,
name : "california"
},
{
cityId:12,
name : "texas"
}]
}
]
I want to access a city name of particular job like below :
var jobId = 101;
var cityId = 12;
var texas = jobDict[jobId].cityDict[cityId] // output: texas
Code:
angular.forEach(response.data, function (data) {
if (jobsDict[data.jobId] == undefined) {
jobsDict[data.jobId] = [];
}
angular.forEach(data.cities, function (city) {
jobsDict[data.jobId].push({
cityDic[city.cityId]: city.name // syntax error here saying unexpected token
});
});
});
I am trying to create a dictionary of jobs and inside a job dictionary, a dictionary of cities.
Can someone please help me fix the issue and achieve the desired output?

Your jobsDict is an array and therefore uses 0-based indexing, not jobID keys.
Likewise for the nested cities.
let jobDict = [{
jobId: 100,
jobName: "Java",
cities: [{
cityId: 10,
name: "chicago"
}, {
statusId: 11,
name: "miami"
}]
}, {
jobId: 101,
jobName: "Python",
cities: [{
cityId: 11,
name: "california"
}, {
cityId: 12,
name: "texas"
}]
}];
let jobId = 101;
let cityId = 12;
let texas =
jobDict.find(job => job.jobId === jobId)
.cities.find(city => city.cityId === cityId)
.name;
console.log(texas);
Following up on your comments, if you're really concerned about performance (which you shouldn't be unless you have 1000's of entries), here's how you can transform the original structure to a 'dictionary' structure that uses the job & city IDs as keys:
let jobs = [{
jobId: 100,
jobName: "Java",
cities: [{
cityId: 10,
name: "chicago"
}, {
cityId: 11,
name: "miami"
}]
}, {
jobId: 101,
jobName: "Python",
cities: [{
cityId: 11,
name: "california"
}, {
cityId: 12,
name: "texas"
}]
}];
let jobsById = Object.fromEntries(jobs.map(({jobId, jobName, cities}) =>
[jobId, {jobName, cities: Object.fromEntries(cities.map(({cityId, name}) => [cityId, name]))}]));
// Equivalent using traditional for loops.
let jobsById2 = {};
for (job of jobs) {
let cities = {};
for (city of job.cities)
cities[city.cityId] = city.name;
jobsById2[job.jobId] = {jobName: job.jobName, cities};
}
console.log(jobsById[101].cities[12]);
console.log(jobsById2[101].cities[12]);

Maybe something like:
const jobArray = [{
jobId: 100,
jobName: "Java",
cities: [{
cityId: 10,
name: "chicago"
},
{
cityId: 11,
name: "miami"
}
]
},
{
jobId: 101,
jobName: "Python",
cities: [{
cityId: 11,
name: "california"
},
{
cityId: 12,
name: "texas"
}
]
}
];
function index_job_array_A(jobArray) {
return jobArray.reduce(
(acc, item) => Object.assign(acc, {
[item.jobId]: Object.assign({}, item, {
cities: item.cities.reduce(
(acc, item) => Object.assign(acc, { [item.cityId]: item }),
{}
)
})
}),
{}
);
};
function index_job_array_B(jobArray) {
let indexed_jobs = {};
jobArray.forEach(function(job) {
let indexed_cities = {};
job.cities.forEach(function(city) {
indexed_cities[city.cityId] = city;
});
indexed_jobs[job.jobId] = { ...job, cities: indexed_cities };
});
return indexed_jobs;
};
const jobDictA = index_job_array_A(jobArray);
const jobDictB = index_job_array_B(jobArray);
console.log(jobDictA['100'].cities['10']);
console.log(jobDictB['100'].cities['10']);

Related

get keys from the nested array of objects

I am looking for a function that can mutate my data i.e array of object with a nested object. It will include keys that have object/array values (it should only include keys with immediate string/number/boolean values).
Example
[
{
id: 1,
person1: {
firstname: "test1",
lastname: 'singh',
address: {
state: "maharashtra",
}
}
},
{
id: 2,
person2: {
firstname: "test2",
lastname: 'rathod',
address: {
state: "kerala",
}
}
},
{
id: 3,
person3: {
firstname: "test3",
lastname: 'gokale',
address: {
state: "Tamilnadu",
}
}
}
]
Expected output
[
{
title: 'person1',
value: 'person.id'
},
{
title: 'person1',
value: 'person.firstname'
},
{
title: 'person1',
value: 'person.lastname'
},
{
title: 'person1',
value: 'person.address'
},
{
title: 'person1',
value: 'person.address.state'
},
...sameforOthers
]
Basically, I need a function that will get an array and will return an array of objects as a given above as expected output
Thanks in advance
I have come up with a solution. below is the link for code sandbox for the
https://codesandbox.io/s/heuristic-rubin-yy2cyy?file=/src/index.js:0-213same
const suggestions = [
{
id: 1,
person1: {
id: "1",
firstname: "test1",
lastname: "singh",
address: {
state: "maharashtra"
},
attributeId: "fhgfgh"
}
}
];
const typeList = ["string", "number", "boolean"];
const getLabelValue = (itemList, initalArr, parentId) => {
if (Array.isArray(itemList)) {
itemList.forEach((currentItem, idx) => {
const id = parentId ? `${parentId}.${idx}` : idx;
if (typeList.includes(typeof currentItem)) {
initalArr.push({
title: id,
value: id
});
} else {
getLabelValue(currentItem, initalArr, id);
}
});
} else {
let keys = Object.keys(itemList);
keys.forEach((currentKey) => {
let currentItem = itemList[currentKey];
const id = parentId ? `${parentId}.${currentKey}` : currentKey;
if (typeList.includes(typeof currentItem)) {
initalArr.push({
title: id,
value: id
});
} else {
getLabelValue(currentItem, initalArr, id);
}
});
}
return initalArr;
};
console.log(">>>>>>>>>", getLabelValue(suggestions, [], ""));

Find synced users from two arrays based on id and return array A with one column from array B

i am trying to find a list of synced users between two arrays (objArray1 & objArray2) and return the data from objArray1 along with 'aid' in Objarray2. I have the below code working, but i am trying to see if can return 'aid' from objArray2 as well in the below format.
Code sample below
// SystemA
const objArray1 = [
{ id: "1", name: "John" },
{ id: "2", name: "Jack" },
{ id: "3", name: "Sam" },
{ id: "4", name: "Bill" },
];
// SystemB
const objArray2 = [
{ id: "1", name: "John", aid:"uuud2905555" },
{ id: "3", name: "Sam" }, aid:"uuud29029303"
{ id: "5", name: "Bob" }, aid:"uuud29435454"
];
const array1IDs = objArray1.map((item) => {
return item.id
})
// Result: array1IDs = ["1", "2", "3", "4"];
const array2IDs = objArray2.map((item) => {
return item.id
})
// Result: array2IDs = ["1", "3", "5"];
// FIND SYNCED USERS
// Compare the id value of each item in objArray1 with each item of objArray2
// Return the ones that match.
const syncedUsers = objArray1.filter((item) => {
const found = objArray2.find((element) => element.id === item.id);
return found;
});
Required JSON Format, please note that all matching items should be returned from objArray1, with the exception of 'aid' from objArray2
{
"records": [
{
"id": {aid}, // from objArray2
"fields": {
"Name":{name}, // from objArray1
"sid": {id} // from objArray1
}
]
}
Presented below is one possible way to achieve the desired objective.
Code Snippet
// method to create result as "JSON"
const createJSON = (arr1, arr2) => (
// use "stringify" to transform JavaScript object into JSON
JSON.stringify({
// set-up the "records" prop
records: arr2
.filter( // filter to keep only those that have matching "id"
({ id }) => arr1.some(ob => ob.id === id)
)
.map( // de-structure & rename props to match desired objective
({ id : sid, name : Name, aid: id }) => ({
id,
fields: {Name, sid}
})
)
})
);
// SystemA
const objArray1 = [
{ id: "1", name: "John" },
{ id: "2", name: "Jack" },
{ id: "3", name: "Sam" },
{ id: "4", name: "Bill" },
];
// SystemB
const objArray2 = [
{ id: "1", name: "John", aid:"uuud2905555" },
{ id: "3", name: "Sam", aid:"uuud29029303" },
{ id: "5", name: "Bob", aid:"uuud29435454" },
];
console.log('result as a JSON: ', createJSON(objArray1, objArray2));
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.
EDIT
Use name and id from array-1. Used restOfArr1Props to account for all other props of array-1 objects to be included.
const createJSON = (arr1, arr2) => (
JSON.stringify({
records: arr1
.filter(
({ id }) => arr2.some(ob => ob.id === id)
)
.map(
({ id : sid, name : Name, ...restOfArr1Props }) => ({
id: arr2.find(a2 => a2.id === sid)?.aid ?? 'missing aid',
fields: {
Name, sid, ...restOfArr1Props
},
})
)
})
);
// SystemA
const objArray1 = [
{ id: "1", name: "John", prop1: 'value11', prop2: 'value12' },
{ id: "2", name: "Jack", prop1: 'value21', prop2: 'value22' },
{ id: "3", name: "Sam", prop1: 'value31', prop2: 'value32' },
{ id: "4", name: "Bill", prop1: 'value41', prop2: 'value42' },
];
// SystemB
const objArray2 = [
{ id: "1", name: "John", aid:"uuud2905555" },
{ id: "3", name: "Sam", aid:"uuud29029303" },
{ id: "5", name: "Bob", aid:"uuud29435454" },
];
console.log('result as a JSON: ', createJSON(objArray1, objArray2));
.as-console-wrapper { max-height: 100% !important; top: 0 }
const objArray1 = [
{ id: '1', name: 'John', type: 'bully' },
{ id: '2', name: 'Jack', type: 'sporty' },
{ id: '3', name: 'Sam', type: 'kind' },
{ id: '4', name: 'Bill', type: 'poliet' },
];
const objArray2 = [
{ id: '1', name: 'John', aid: 'uuud2905555' },
{ id: '3', name: 'Sam', aid: 'uuud29029303' },
{ id: '5', name: 'Bob', aid: 'uuud29435454' },
];
const syncedUsers = { records: [] };
for (let user1 of objArray1) {
const foundUser = objArray2.find(user2 => user2.id === user1.id);
if (foundUser) {
syncedUsers.records.push({
id: foundUser.aid,
fields: { sid: user1.id, name: user1.name, ...user1 },
});
}
}
console.log(JSON.stringify(syncedUsers));

Search objects for a given string

I have these objects
const data = [
{
id: 1,
recipient: "001",
assessment: "Apta",
score: "2",
ovarian: "E1",
},
{
id: 2,
recipient: "ABC2",
assessment: "Apta",
score: "2,5",
ovarian: "E1",
},
{
id: 3,
recipient: "003",
assessment: "Refugo",
score: "3",
ovarian: "E1",
},
{
id: 4,
recipient: "004",
assessment: "Apta",
score: "4",
ovarian: "E2",
},
];
And this is my code, which when it finds the correct string it returns me:
const searchAnimal = value => {
setInput(value);
JSON.parse(records).filter(item => {
if (item.recipient === value) {
setSearch([item]);
}
});
};
What would the logic be to return all object.recipients that start with 00? Would a regex maybe do it?
I think changing a little bit the logic would help:
let search = function (data, searchString) {
return data.filter((item) => {
return item.recipient.includes(searchString);
});
};
By doing so will give you the object you're searching for.
You can filter for the objects with a recipient that starts with 00 by using:
const array00Animals = data.filter((animal) => animal.recipient.substr(0, 2) === '00');
This will return the array of objects but only id's 1, 3 and 4 from your sample data.

Group an array of object having nested level

I have a tabular mode array object as shown below upto n level. it can be any parent children's records
var records = [
{ country: "USA", state: "FLORIDA", city: "city1" },
{ country: "USA", state: "FLORIDA", city: "city2" },
{ country: "USA", state: "FLORIDA", city:"city3" },
{ country: "USA", state: "ALASKA" },
{ country: "USA", state: "ALBAMA" },
]
var columns = ["country","state","city"] // upto n column
I need to group in below format for nth level as there can be n level of relations, group records in below format
{
sequencer: 1, value: 'USA', loop: [
{ sequencer: 1, value: 'FLORIDA', loop: [
{ sequencer: 1, value: 'city1' },
{ sequencer: 2, value: 'city2' },
{ sequencer: 3, value: 'city3' },
], },
{ sequencer: 2, value: 'ALASKA' },
{ sequencer: 3, value: 'ALBAMA' },
],
}
Can someone write an recursive function to group for n level of column object.
Thanks
You could group the data by avoiding unwanted loop properties.
const
data = [{ country: "USA", state: "FLORIDA", city: "city1" }, { country: "USA", state: "FLORIDA", city: "city2" }, { country: "USA", state: "FLORIDA", city: "city3" }, { country: "USA", state: "ALASKA" }, { country: "USA", state: "ALBAMA" }],
keys = ['country', 'state', 'city'],
result = data.reduce((loop, o) => {
keys
.map(k => o[k])
.filter(Boolean)
.reduce((r, value) => {
let temp = (r.loop ??= []).find(q => q.value === value);
if (!temp) r.loop.push(temp = { sequence: r.loop.length + 1, value });
return temp;
}, { loop });
return loop;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I answered a similar question recently. You could write your transform using flatMap and recursion -
const transform = ([ name, ...more ], { value, loop = [{}] }, r = {}) =>
name === undefined
? [ r ]
: loop.flatMap(t => transform(more, t, { [name]: value, ...r }))
const records =
{sequencer:1,value:'USA',loop:[{sequencer:1,value:'FLORIDA',loop:[{sequencer:1,value:'city1'},{sequencer:2,value:'city2'},{sequencer:3,value:'city3'}]},{sequencer:2,value:'ALASKA'},{sequencer:3,value:'ALBAMA'}]}
const columns =
['country', 'state', 'city']
const result =
transform(["country", "state", "city"], records)
console.log(JSON.stringify(result, null, 2))
A function statement equivalent of the => expression above -
function transform
( [ name, ...more ]
, { value, loop = [{}] }
, r = {}
)
{ if (name === undefined)
return [ r ]
else
return loop.flatMap
( t =>
transform
( more
, t
, { [name]: value, ...r }
)
)
}
Read the original Q&A for more insight on this technique.

How to pull nested object based on string match?

activePath would change dynamically based on api call , how to pull object based on the activePath string that matches in nested object ?
path examples : Drug/GetRefills in this case it should push data.Drug.getRefills and if path is Payment/getAccount it should push data.Payment.getAccount
main.js
const data =
[{
id: 11,
name: "Drug",
children: [{
id: 12,
name: "getRefills"
}, {
id: 13,
name: "getDetails"
}]
}, {
id: 14,
name: "Payment",
children: [{
id: 15,
name: "getAccount"
}, {
id: 16,
name: "getAccountDetails"
}]
}]
function getModelData(data){
var activePath = "Drug/GetRefills";
var _interfaces = [];
$.each(data, function(id, item){
if (activePath.toLowerCase().includes(item.name)) {
console.log('OBJ', item);
_interfaces.push(item); // it should push getrefills object into interfaces
}
});
return _interfaces;
}
You can use recursion to find the object (similar to DFS):
const data = [{
id: 11,
name: "Drug",
children: [{
id: 12,
name: "getRefills"
}, {
id: 13,
name: "getDetails"
}]
}, {
id: 14,
name: "Payment",
children: [{
id: 15,
name: "getAccount"
}, {
id: 16,
name: "getAccountDetails"
}]
}];
function getModelData(path) {
function find(arr, [key, ...rest]) {
const obj = arr.find(o => o.name === key);
if (!obj) return null;
return rest.length ? find(obj.children || [], rest) : obj;
}
return find(data, path.split('/'));
// Instead of returning, add the found object to _interfaces
}
console.log(getModelData('Drug/getRefills'));
console.log(getModelData('Drug/getRefillsss'));
console.log(getModelData('Payment/getAccountDetails'));
I think you are looking for some util like flat. Here is the very basic example.
const data = [
{
id: 11,
name: "Drug",
children: [
{
id: 12,
name: "getRefills"
},
{
id: 13,
name: "getDetails"
}
]
},
{
id: 14,
name: "Payment",
children: [
{
id: 15,
name: "getAccount"
},
{
id: 16,
name: "getAccountDetails"
}
]
}
];
function flat(array) {
return array.reduce((m, {name, children}) => {
children.forEach((child) => {
const {name:cname} = child
const fullName = `${name.toLowerCase()}/${cname.toLowerCase()}`
if(!m[fullName]) m[fullName] =[]
m[fullName].push(child)
})
return m
},{})
}
function getModelData(path, data) {
return flat(data)[path.toLowerCase()];
}
var activePath = "Drug/GetRefills";
console.log(getModelData(activePath, data));
//Output
[ { id: 12, name: 'getRefills' } ]
Here is an example how you can get the right object from the data with the filter function from lodash.
const activePath = "Drug/getRefills";
// get name
let name = activePath.substr(0, activePath.indexOf('/'));
// get detail
let detail = activePath.substr(activePath.indexOf('/') + 1);
const data =
[{
id: 11,
name: "Drug",
children: [{
id: 12,
name: "getRefills"
}, {
id: 13,
name: "getDetails"
}]
}, {
id: 14,
name: "Payment",
children: [{
id: 15,
name: "getAccount"
}, {
id: 16,
name: "getAccountDetails"
}]
}]
// Get data with lodash filter
const currentName = _.filter(data, d => d.name === name);
const currentDetail = _.filter(currentName[0].children, c => c.name === detail);
console.log(currentDetail[0]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
const data = [{
id: 11,
name: "Drug",
children: [{
id: 12,
name: "getRefills"
}, {
id: 13,
name: "getDetails"
}]
}, {
id: 14,
name: "Payment",
children: [{
id: 15,
name: "getAccount"
}, {
id: 16,
name: "getAccountDetails"
}]
}];
function getModelData(data,activePath){
var activePaths = activePath.split("/"),
_interfaces = [];
$.each(data, function(index, item){
if(!item.children || item.children.length == 0){
return false; //break
}
if(activePaths[0].toLowerCase() != item.name.toLowerCase()){
return true;//continue
}
childs = item.children;
$.each(childs,function(name,item){
item.name.toLowerCase() === activePaths[1].toLowerCase() && _interfaces.push(item);
});
});
return _interfaces;
}
console.log(getModelData(data,'Drug/getRefills'));
console.log(getModelData(data,'Payment/getAccountDetails'));

Categories

Resources