I have a data like this:
[
{
user_id: 356793,
bets: [
{
key: 'total',
team: {
away: 1959,
home: 1418
},
value: 1.76,
match_game: {
score: {
away: 17,
home: 18
}
}
}
]
}
]
And I want to transform it into paths or just log the paths, like this:
data[i].user_id
data[i].bets
data[i].bets[i]
data[i].bets[i].key
data[i].bets[i].team
data[i].bets[i].team.away
data[i].bets[i].team.home
data[i].bets[i].value
data[i].bets[i].match_game
data[i].bets[i].match_game.score
data[i].bets[i].match_game.score.away
data[i].bets[i].match_game.score.home
I think recursion does the trick here but it throws a RangeError: Maximum call stack size exceeded. And I don't know where it fails. It works on the first array but on the second array, it fails and causes an infinite loop.
Here's my code:
const data = [
{
user_id: 356793,
bets: [
{
key: 'total',
team: {
away: 1959,
home: 1418
},
value: 1.76,
match_game: {
score: {
away: 17,
home: 18
}
}
}
]
}
]
const isArray = hit => Array.isArray(hit)
const isObject = hit => !isArray(hit) && typeof hit === 'object'
const isNumber = hit => typeof hit === 'number'
const isString = hit => typeof hit === 'string'
const isNonIterable = hit => !isArray(hit) && !isObject(hit)
const toPaths = (payload, prefix) => {
if (isArray(payload)) {
for (let i = 0; i < data.length; i++) {
const currData = data[i]
toPaths(currData, prefix + '[i]')
}
return
}
if (isObject(payload)) {
for (const key in payload) {
const currData = payload[key]
if (isNonIterable(currData)) {
console.log(`${prefix}.${key}`)
continue
}
if (isArray(currData)) {
for (let i = 0; i < data.length; i++) {
const currData = data[i]
toPaths(currData, prefix + '[i]')
}
continue
}
// console.log(`${prefix}.key`)
}
return console.log(prefix)
}
}
toPaths(data, 'bets')
In two places, you iterate over data while you were supposed to use payload:
for (let i = 0; i < data.length; i++) {
Related
I want to get my file directories as nested array object but i can't seem to figure out how to convert
[
'routes/files',
'routes/files/emptyfolder',
'routes/files/somefolder',
'routes/files/somefolder/example.docx',
'routes/files/test.docx',
'routes/randomdata.json'
]
to
[
{
title: 'routes',
content: [
{
title: 'files',
content: [
{
title: 'empty folder',
content: []
},
{
title: 'somefolder',
content: [
{
title: 'example.docx',
},
]
},
{
title: 'test.docx',
}
],
},
{
title: 'randomdata.json'
}
],
}
]
it looks impossible problem for me to solve.
I would love to know how to solve it.
Thank you.
Here is how I solved it:
Not the best solution, but works.
const arr = [
"routes/files",
"routes/files/emptyfolder",
"routes/files/somefolder",
"routes/files/somefolder/example.docx",
"routes/files/test.docx",
"routes/randomdata.json",
];
const arr2 = arr.map((p) => p.split("/"));
const setNestedObjectField = (
obj,
props,
value
) => {
if (!Array.isArray(obj)) {
if (!obj.content) {
obj.content = [];
}
obj = obj.content;
}
for (const propName of props) {
const next = obj.find((el) => el.title === propName);
if (!next) {
console.assert(props.at(-1) === propName);
// last propName
obj.push(value);
} else {
if (!next.content) {
next.content = [];
}
obj = next.content;
}
}
};
const rez = [];
let index = 0;
while (arr2.some((s) => s[index] !== undefined)) {
// arr2 = arr2.filter((a) => a.length);
const layer = arr2.reduce((acc, pathArr) => {
if (pathArr[index] === undefined) return acc;
acc.add(pathArr.slice(0, index + 1).join("/"));
return acc;
}, new Set());
// console.log({ layer });
for (const key of layer) {
setNestedObjectField(rez, key.split("/"), { title: key.split("/").at(-1) });
}
index++;
}
console.log(rez);
I came across this question and it's an interesting problem, I know it's already been answered, but I wanted to spend a little of my time to solve it my way.
here I leave my code:
function nestedDirectories (arr) {
const splittedArray = arr.map(a => a.split('/'));
return {
mergeObjs: function(target, source) {
for (let key in source) {
if(!target[key]) target[key] = {};
target[key] = this.mergeObjs(target[key], source[key]);
}
return target;
},
buildResponse: function (objMain) {
let arr = [];
for (let key in objMain) {
let o = { title: key, content: [] };
if(key.includes(".")) {
delete o.content;
} else if (Object.keys(objMain[key]).length) {
o.content = this.buildResponse(objMain[key]);
}
arr.push(o);
}
return arr;
},
exec: function () {
let targetObject = {};
splittedArray.forEach(arrParent => {
let strObj = '';
for (let i = arrParent.length - 1; i >= 0 ; i--) {
strObj = `"${arrParent[i]}": {${strObj}}`;
}
let parseObj = JSON.parse(`{${strObj}}`);
targetObject = this.mergeObjs(targetObject, parseObj);
});
return this.buildResponse(targetObject);
}
}
}
and use it like this:
const dirs = [
'routes/files',
'routes/files/emptyfolder',
'routes/files/somefolder',
'routes/files/test.docx',
'routes/randomdata.json',
'routes/files/somefolder/example.docx'
];
const data = nestedDirectories(dirs).exec();
result:
[
{
title: 'routes',
content: [
{
title: 'files',
content: [
{ title: 'emptyfolder', content: [] },
{
title: 'somefolder',
content: [ { title: 'example.docx' } ]
},
{ title: 'test.docx' }
]
},
{ title: 'randomdata.json' }
]
}
]
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I have an object like this:
const obj = {
name: 'john',
children: [
{
name: 'Foo'
},
{
name: 'Bar',
children: [
{
name: 'Doe'
}
]
}
]
}
And I have to create a function to find the object with the specified name.
My code can find the object with the name, but it doesn't return the object.
const search = (node, name) => {
return searchInObj(node, name);
};
const searchInObj = (obj, name) => {
if (obj.name === nodeName) {
return obj;
} else {
if (obj.children) {
searchInArr(obj.children, name);
}
}
};
const searchInArr = (arr, name) => {
for (let i = 0; i < arr.length; i++) {
searchInObj(arr[i], name);
}
};
If I put
console.log(search(obj, 'Doe')) // return undefined
It just work if I looking for john
Return the result for searchInObj function.
const obj = {
name: 'john',
children: [
{
name: 'Foo'
},
{
name: 'Bar',
children: [
{
name: 'Doe'
}
]
}
]
}
const search = (node, name) => {
return searchInObj(node, name);
};
const searchInObj = (obj, name) => {
if (obj.name === name) {
return obj;
} else {
if (obj.children) {
return searchInArr(obj.children, name);
}
}
};
const searchInArr = (arr, name) => {
for (let i = 0; i < arr.length; i++) {
const result = searchInObj(arr[i], name);
if (result !== undefined) return result
}
};
console.log(search(obj, 'Doe')) ///This will return object
Just add return statements, like #quentin said
const obj = {
name: 'john',
children: [
{
name: 'Foo'
},
{
name: 'Bar',
children: [
{
name: 'Doe'
}
]
}
]
}
const search = (node, name) => {
return searchInObj(node, name);
};
const searchInObj = (obj, name) => {
// Typo here? what is nodeName
if (obj.name === name) {
return obj;
} else {
if (obj.children) {
// Added return
return searchInArr(obj.children, name);
}
}
};
const searchInArr = (arr, name) => {
for (let i = 0; i < arr.length; i++) {
// Return if found
const result = searchInObj(arr[i], name);
if (result !== undefined) return result
}
};
console.log(search(obj, 'Doe'))
Following are the code snippet for the data object which contains the information for the codeworks array representing the code and text.
I have one code key array like code = ["ABC","MDH"] and I want the expected out as represented into the code snippets.
const data = {
pData: {
data: [
{
codeworks: [
{
code: "MDH",
text: "Total Care MDH0"
},
{
code: "MDH",
text: "Total Care MDH1"
},
{
code: "MDH",
text: "Total Care MDH2"
}
]
},
{
codeworks: [
{
code: "ABC",
text: "Total Care ABC"
},
{
code: "MDH",
text: "Total Care MDH"
}
]
},
{
codeworks: [
{
code: "MDH",
text: "text0"
},
{
code: "XYZ",
text: "text1"
}
]
}
]
}
};
code = ["ABC","MDH"]
Expected Output : ['Total Care MDH0','Total Care ABC','text0']
I tried using the following ways,
const networkCodes = ["ABC", "MDH"];
if (
data &&
data.pData&&
data.pData.data &&
data.pData.data.length > 0
) {
const pDataItems = data.pData.data;
let filteredItems = [];
const acceptingNewItems =
pDataItems &&
pDataItems.length > 0 &&
pDataItems.forEach((providerInfoObj, index) => {
const networks =
providerInfoObj &&
providerInfoObj.codeworks&&
providerInfoObj.codeworks.length > 0 &&
providerInfoObj.codeworks;
/* eslint-disable-next-line */
for (let j = 0; j < networks.length; j++) {
const ele = networks[j];
const findNetworkCodes =
networkCodes && networkCodes.length > 0 && networkCodes;
for (let index = 0; index < findNetworkCodes.length; index++) {
const element = findNetworkCodes[index];
if (element === ele.code) {
filteredItems.push(ele.text);
}
}
}
//return filteredItems ;
});
console.log(filteredItems );
}
I did not get the output as expected into the snippets as denoted.
Thanks.
Your code is too long to understand. I think it could be expressed in short like below.
const res = data.pData.data
.map(({codeworks}) => {
const matchedCodework = codeworks.find(codework => code.includes(codework.code));
return matchedCodework ? matchedCodework.text : null;
})
.filter(text => text != null)
console.log(res)
I have an array of objects
Deep inside those objects is a text string
I want to check if other objects in the same array have the same text string / are duplicates.
Then i need a new array with those duplicates removed.
I thought this would be quite simple but it's been testing my intellect for two days now.
const arr = [
{..obj 1}
{..obj 2}
{..obj 3}
{
id: 4,
uid: 24872-2847-249249892842,
tags: ['some', 'stuff'],
type: "blogpage",
href: "https://link-to-stuff",
first_publication_date: "2020-02-12T16:05:04+0000",
last_publication_date: "2020-02-18T21:52:06+0000",
data: {
...some stuff
heading: [
{ type: "heading1", text: "Here Is My Text I Need To Check Duplicates
Of"}
]
}
}
{..obj 5}
{..obj 6}
{..obj 7}
{..obj 8}
{..obj 9}
{..obj 10}
]
I figured something like:
filterOutDuplicates = (blogIndexContent) => {
let arr = blogIndexContent.pages;
let results = [];
arr.map(each => {
if (!results || !results.length) {
results.push(each);
} else {
for (let i = 0; i < results.length; i++) {
const headline = results[i].data.heading[0].text;
if (headline === each.data.heading[0].text) {
return;
} else {
return results.push(each);
}
}
}
})
console.log('Results :', results); // <-- this just gives me the same 9 blog stories again, no duplicates removed.
}
What am i doing wrong guys?
If you dont mind using lodash, it could be easily solved using _.uniqBy
const withoutDups = _.uniqBy(arr, 'data.heading[0].text')
Try this
const arr = [
{
id: 4,
data: {
heading: [
{
type: "heading1",
text: "Here Is My Text I Need To Check Duplicates Of"
}
]
}
},
{
id: 5,
data: {
heading: [
{
type: "heading1",
text: "Here Is My Text I Need To Check Duplicates Of"
}
]
}
},
{
id: 6,
data: {
heading: [
{
type: "heading1",
text: "Not Duplicates"
}
]
}
}
];
const withoutDuplicates = arr.reduce(
(prev, curr) =>
prev
.map(d => d["data"]["heading"][0]["text"])
.includes(curr["data"]["heading"][0]["text"])
? [curr]
: [...prev, curr],
[]
);
console.log(withoutDuplicates);
Slight changes to your code
1) remove using map, have loop over array.
2) Build the uniq object with keys. (Here headline is what we want)
3) Add to results array only when key is not in uniq
let arr = blogIndexContent.pages;
let results = [];
const uniq = {};
for (let i = 0; i < arr.length; i++) {
const headline = arr[i].data.heading[0].text;
if (!(headline in uniq)) {
results.push(each);
uniq[each] = 1;
}
}
console.log("Results :", results);
This should work for you:
filterOutDuplicates = blogIndexContent => {
let arr = blogIndexContent.pages
const result = []
arr.forEach(each => {
if (result.length === 0) {
result.push(each)
}
else {
const headline = each.data.heading[0].text
let found = false
for (let i = 0; i < result.length; i++) {
if (result[i].data.heading[0].text === headline) {
found = true
break
}
}
if (!found) {
result.push(each)
}
}
})
console.log('Results :', results)
}
I made the following function which traverses an object recursively and tries to find if a property exists in that object. If it does, it returns that property and null if it is not found:
export const findNestedPropertyInObject = (sourceObject: any, targetKey: string) => {
let results: any;
const maxIterations = 100;
let currentIteration = 0;
const searchInObject = (obj: any, targetKey: string) => {
const keys = obj.length ? [] : Object.keys(obj);
if (keys && keys.length) {
if (keys.includes(targetKey)) {
results = obj[targetKey];
return;
} else {
keys.forEach((key: string) => {
if (currentIteration >= maxIterations) {
return;
}
currentIteration++;
searchInObject(obj[key], targetKey);
});
}
}
};
searchInObject(sourceObject, targetKey);
return results;
};
this is the sample object:
const aggregations = {
most_used_skills: {
doc_count: 388,
skill: {
doc_count_error_upper_bound: 10,
sum_other_doc_count: 325,
buckets: [
{
key: 'C++ Programming Language',
doc_count: 15,
},
{
key: 'Javascript',
doc_count: 14,
},
{
key: 'ExtJS',
doc_count: 12,
},
{
key: 'Amazon Web Services',
doc_count: 11,
},
{
key: 'Android',
doc_count: 11,
},
],
},
},
};
this is how i am invoking it:
console.log(findNestedPropertyInObject(aggregations, 'buckets'));
My question is that, how can i optimize this method? What safety checks can i add to this to make it more fault tolerant and robust?
export const findNestedPropertyInObject = (sourceObject: any, targetKey: string) => {
let results: any;
const maxIterations = 100;
let currentIteration = 0;
const searchInObject = (obj: any, targetKey: string) => {
const keys = (obj.length)? obj : Object.keys(obj); // if obj is object get keys as an array
if ( currentIteration < maxIterations && typeof keys === 'object') // checking if it actually an Array (js treat array as object type)
{
if (keys.includes(targetKey))
{
results = obj[targetKey];
currentIteration = maxIterations; // to stop recursive calling
return; //optional
}
else
{
keys.forEach((key: any) => {
currentIteration++;
const innerkeys = (obj[key])? obj[key] : key; // to check if 'key' is key of object or object itself
searchInObject(innerkeys, targetKey);
});
}
}
};
searchInObject(sourceObject, targetKey);
return results
};