how to format an object of array to a new one - javascript

I'm trying to transform an object contain array to another one with javascript. Below is an example of the object field and what the formatted one should look like.
The data after formating must show me only fileds who has the "ABS" in funcName
let beforeData = {
SUMMER: [
{ funcName: '{{WORKING_ABS}}', subject: { en: "Exercice1"} },
{ funcName: '{{PULLS_BODY}}', subject: { en: "Exercice2"} },
],
WINTER: [
{ funcName: '{{FULL_BODY}}', subject: { en: "Exercice3"} },
{ funcName: '{{REST_ABS}}', subject: { en: "Exercice4"} },
]
};
I need The object to be exactly like this one
let AfterData ={
worklinks: [
{
name: 'Exercice1',
link: '{{WORKING_ABS}}',
},
{
name: 'Exercice4',
link: '{{REST_ABS}}',
},
]
},
I was trying to make a method like this one (Its just a draft ) , maybe somone will help to improve this method
export const functTransform = (dataaas) => { Object.keys(dataaas).map(fiels => ({
worklinks =>funcName.search("ABS") > -1).map(({funcName, subject}) => ({
link: funcName,
name: subject.en
}))};
I'm new working with javascript so any help is greatly appreciated, Thanks.

Consider following code:
const beforeData = {
SUMMER: [
{ funcName: '{{WORKING_ABS}}', subject: { en: "Exercice1"} },
{ funcName: '{{PULLS_BODY}}', subject: { en: "Exercice2"} },
],
WINTER: [
{ funcName: '{{FULL_BODY}}', subject: { en: "Exercice3"} },
{ funcName: '{{REST_ABS}}', subject: { en: "Exercice4"} },
]
};
const isABS = (str) => str.indexOf('ABS') > -1;
const result = Object.values(beforeData).flat().map(o => ({link: o.funcName, name: o.subject.en})).filter(o => isABS(o.link));
console.log(result);

You could do it like this? (Reduce with forEach)
let beforeData = {
SUMMER: [
{ funcName: '{{WORKING_ABS}}', subject: { en: "Exercice1"} },
{ funcName: '{{PULLS_BODY}}', subject: { en: "Exercice2"} },
],
WINTER: [
{ funcName: '{{FULL_BODY}}', subject: { en: "Exercice3"} },
{ funcName: '{{REST_ABS}}', subject: { en: "Exercice4"} },
]
};
function transform(inputData, funcComparator){
if (funcComparator == undefined){
funcComparator = (item) => item.funcName.includes("ABS");
}
return Object.values(inputData).reduce((aggArr, arr) => {
arr.forEach(item => {
if (funcComparator(item)){
const itemCopy = {name: item.subject.en, link: item.funcName};
aggArr.push(itemCopy);
}
})
return aggArr;
}, []);
}
//use it to find all your "ABS":
console.log(transform(beforeData));
//another example, use it to find all your "BODY":
//console.log(transform(beforeData, (item) => item.funcName.includes("BODY")));
Output:
[
{
"name": "Exercice1",
"link": "{{WORKING_ABS}}"
},
{
"name": "Exercice4",
"link": "{{REST_ABS}}"
}
]

Related

Javascript - check if certain values are in an array of objects

Say I have an array of 5 objects, each with 2 keys (eg, 'title' & 'author').
I want to check the truthiness that 3 SPECIFIC titles exist in the array.
What's the best way to do that?
I have the following... but it doesn't seem very efficient:
const books = [
{ title: 'Book1', author: 'Author1' },
{ title: 'Book2', author: 'Author2' },
{ title: 'Book3', author: 'Author3' },
{ title: 'Book4', author: 'Author4' },
{ title: 'Book5', author: 'Author5' },
];
const certainBooks = books.some((b) => b.title === 'Book2')
&& books.some((b) => b.title === 'Book3')
&& books.some((b) => b.title === 'Book5')
if (certainBooks) {
// Do stuff
}
If the values and number of titles is dynamic, it might be worth creating an index of titles in the array; something with O(1) time complexity for faster lookups
const books = [
{ title: 'Book1', author: 'Author1' },
{ title: 'Book2', author: 'Author2' },
{ title: 'Book3', author: 'Author3' },
{ title: 'Book4', author: 'Author4' },
{ title: 'Book5', author: 'Author5' },
];
const titleIndex = new Set(books.map(({ title }) => title));
const titlesExist = (...titles) =>
titles.every(title => titleIndex.has(title))
console.log("Book2, Book3, Book5:", titlesExist("Book2", "Book3", "Book5"));
console.log("Book1:", titlesExist("Book1"));
console.log("Book5, Book6:", titlesExist("Book5", "Book6"));
A more general approach would be to map the books to their titles, then check that .every one of the titles you're looking for exists.
const books = [
{ title: 'Book1', author: 'Author1' },
{ title: 'Book2', author: 'Author2' },
{ title: 'Book3', author: 'Author3' },
{ title: 'Book4', author: 'Author4' },
{ title: 'Book5', author: 'Author5' },
];
const titles = books.map(({ title }) => title);
const toFind = ['Book2', 'Book3', 'Book5'];
if (toFind.every(title => titles.includes(title))) {
console.log('do stuff');
}
If the array of books is large, you could benefit by making titles a Set instead of an array - Set#has is faster than Array#includes when there are a lot of elements.
You could loop over them
const books = [
{ title: "Book1", author: "Author1" },
{ title: "Book2", author: "Author2" },
{ title: "Book3", author: "Author3" },
{ title: "Book4", author: "Author4" },
{ title: "Book5", author: "Author5" },
];
const booksNeeded = ["Book2", "Book3", "Book4"];
for (let book of books) {
const lookForIndex = booksNeeded.findIndex(
(title) => title.toLowerCase() === book.title.toLowerCase()
);
if (lookForIndex !== -1) {
booksNeeded.splice(lookForIndex, 1);
}
if (!booksNeeded.length) {
break; // Early break if all the books has been found
}
}
if (!booksNeeded.length) {
console.log("Do Something");
} else {
console.log("Something else");
}
const books = [
{ title: 'Book1', author: 'Author1' },
{ title: 'Book2', author: 'Author2' },
{ title: 'Book3', author: 'Author3' },
{ title: 'Book4', author: 'Author4' },
{ title: 'Book5', author: 'Author5' },
];
let ops = 0;
let search = [ "Book2", "Book3", "Book4" ];
let { length } = search;
for ( let i = 0, len = books.length; length && i < len; i++ ){
ops++;
if ( search.includes(books[i].title) ){
length--;
}
}
if ( !length ){
console.log("All books found!");
} else {
console.log("Not all books found!")
}
console.log( "Number of operations: ", ops );

Converting an array to an object of nested objects for a tree diagram in Javascript

i'm attempting to create a Tree Diagram with react-d3-js. It needs to be in a specific format. So i need to convert the initial data that i have to the format.
This is a diagram for a shop to see the distribution chain and who is allowed to make a purchase from specific nodes.
Initial Data:
store.name = 'Absolut Chocolat' //Main Parent
store.shopconditions: [
{
"role": "agent",
"condition": ["owner", "stokist"]
},
{
"role": "stokist",
"condition": ["owner", "master stokist"]
},
{
"role": "master stokist",
"condition": ["owner"]
}
]
// If role is agent, then they are allowed to buy from 'owner' and 'stokist'
Here's the hardcoded ideal output:
orgChart = {
name: 'Absolut Chocolat',
children: [
{ name: 'Agent' },
{
name: 'Stokist',
children: [
{
name: 'Agent',
},
],
},
{
name: 'Master Stokist',
children: [
{
name: 'Stokist',
children: [
{
name: 'Agent',
},
],
},
],
},
],
};
With a few for each loops, i've gotten to the first 2 layers of the intended output but i cannot find a way to get more than that.
Here is what i got so far:
Agent node is not under Master Stokist
Current code:
let chartData = { name: store.name, children: [] };
store.shopconditions.forEach((i) => {
i.condition.forEach((c) => {
if (c === 'owner') {
chartData.children.push({ name: i.role });
}
});
});
const chartDataParser = (data) => {
data.children.map((i) => {
for (const [k, v] of Object.entries(i)) {
store.shopconditions.forEach((c) => {
c.condition.forEach((o) => {
if (o === v) {
if (!i.children) {
i.children = [{ name: c.role }];
} else {
i.children.push({ name: c.role });
}
}
});
});
}
});
};
chartDataParser(chartData);
Current output:
{
name: 'Absolut Chocolat',
children: [
{ name: 'Agent' },
{
name: 'Stokist',
children: [
{
name: 'Agent',
},
],
},
{
name: 'Master Stokist',
children: [
{
name: 'Stokist',
// Missing children: Agent Node
},
],
},
],
};
What the tree diagram should look like:
As you can see under Master Stokist node, Agent is under Stokist
The Agent node is not reached under the stokist node in the right most chain. I need a fix to my current code so it can go to that extra layer. Thanks in advance. Looking forward to learn from your answers.
You can build an object that lists children by role and then use that to recursively build the nodes of the object. Possibly something like the following:
const store = {
name: 'Absolut Chocolat',
shopconditions: [
{ "role": "agent", "condition": ["owner", "stokist"], name: 'Agent' },
{ "role": "stokist", "condition": ["owner", "master stokist"], name: 'Stockist' },
{ "role": "master stokist", "condition": ["owner"], name: 'Master Stockist' },
]
};
const build_role_map = (store) => {
let role_map = Object.fromEntries(
store.shopconditions.map((v) => [v.role, { ...v, children: [] }])
);
role_map.owner = { "role": "owner", "condition": [], children: [], name: store.name };
store.shopconditions.forEach(
({ role, condition }) => {
condition.forEach((parent) => { role_map[parent].children.push(role) })
}
);
return role_map;
};
const build_node = (role_map, { name, children }) => {
let node = { name };
if(children.length > 0)
node.children = children.map((child) => build_node(role_map, role_map[child]));
return node;
};
const build_tree = (store) => {
const role_map = build_role_map(store);
return build_node(role_map, role_map.owner);
};
console.log(build_tree(store));

rethinkDB: get first key name in an object

I'm just starting with rethinkDB query lang and don't understand how to select the first key (name).
In this case I would be the object notes.
I did it with Object.keys(t)[0]; tries that just returns me args, what am I doing wrong?
{
id: "mission#0",
info:
"Tokyo",
**//how to get the value of content ?**
note: {
"note#032b8836-f647-4165-9ec9-fc22769f3ffa": {
content: "hello world",
context: "all",
glyphId: "glyph#default",
id: "note#032b8836-f647-4165-9ec9-fc22769f3ffa",
meta: {
context: null,
createdAt: 1624044683953,
id: "note#032b8836-f647-4165-9ec9-fc22769f3ffa",
links: null,
parentEntity: "mission#0b1cd61d-bb36-4cf8-8f3d-9cc9b14ff054",
references: { glyphId: "glyph" },
rootAggregateId: "mission#0b1cd61d-bb36-4cf8-8f3d-9cc9b14ff054",
rootAggregatePath: [
"private",
"notes",
"note#032b8836-f647-4165-9ec9-fc22769f3ffa",
],
status: "published",
summaries: {
description: "hello world",
glyph: "bookmark",
glyphColor: "base",
info: "hello world",
},
type: "note",
values: null,
version: 0,
},
},
}
function* extract(next) {
const q = r
.db("test")
.table("mission")
.getAll(true, { index: "recurrenceEnabled" })
.filter((mission) => mission("meta")("status").eq("published"))
.map((m) => {
let t = m("private")("notes");
let p = Object.keys(t)[0];
return {
note: t,
id: m("id"),
info: m("meta")("summaries")("info"),
};
});
return yield q.run(con, next);
}
Thank you for the reading !

Javascript - transforming an object of array list to new formated one?

I'm trying to transform an object contain array to another one with javascript. Below is an example of the object field and what the formatted one should look like.
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
I need The new Fields to looks like this
let newFields = {
name: 'GAME',
tags:[
{ name: 'playPES', value: "{{PES}}" },
{ name: 'playFIFA', value: "{{FIFA}}" }
]},
One contributor suggested me a method like this but i think something need to modify in it but couldn't figure it out.
export const transform = (fields) => ({
tags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
tags: innerFields.map(({code, title: title: {en})=>({name: en, value: code}))
}))
});
// newFields= transform(Fields)
I'm new working with javascript so any help is greatly appreciated, Thanks.
const transform = (o) => {
return Object.entries(o).map((e)=>({
name: e[0],
tags: e[1].map((k)=>({name: (k.title)?k.title.en:undefined, value: k.code}))
}))[0]
}
console.log(transform({
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
}))
Using the entries method you posted:
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
// 1. Obtain keys and values from first object
Fields = Object.entries(oldFields);
// 2. Create new object
const newFields = {};
// 3. Create the name key value pair from new Fields array
newFields.name = Fields[0][0];
// 4. Create the tags key value pair by mapping the subarray in the new Fields array
newFields.tags = Fields[0][1].map(entry => ({ name: entry.title.en, value: entry.code }));
Object.entries(Fields) will return this:
[
"GAME",
[TagsArray]
]
And Object.entries(Fields).map will be mapping this values.
The first map, will receive only GAME, and not an array.
Change the code to something like this:
export const transform = (Fields) => {
const [name, tags] = Object.entries(Fields);
return {
name,
tags: tags.map(({ code, title }) => ({
name: title.en,
value: code
}))
}
}
Hope it help :)
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
let newFields = {
name: 'GAME',
tags:[
{ name: 'playPES', value: "{{PES}}" },
{ name: 'playFIFA', value: "{{FIFA}}" }
]
}
let answer = {
name: "Game",
tags: [
]
}
Fields.GAME.map(i => {
var JSON = {
"name": i.title.en,
"value": i.code
}
answer.tags.push(JSON);
});
console.log(answer);
I think that this is more readable, but not easier... If you want the result as object you need to use reduce, because when you do this
Object.keys(Fields)
Your object transform to array, but reduce can change array to object back.
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
const result = Object.keys(Fields).reduce((acc, rec) => {
return {
name: rec,
tags: Fields[rec].map(el => {
return {
name: el.title.en,
value: el.code
}
})
}
}, {})
console.log(result)
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
const transform = (fields) => ({
tags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
tags: innerFields.map(({code, title: title,en})=>({name: title.en, value: code}))
}))
});
//check required output in console
console.log(transform(Fields));

Create a key map for all paths in a recursive/nested object array

I have an n levels deep nested array of tag objects with title and ID. What I'm trying to create is a an object with IDs as keys and values being an array describing the title-path to that ID.
I'm no master at recursion so my attempt below doesn't exactly provide the result I need.
Here's the original nested tag array:
const tags = [
{
title: 'Wood',
id: 'dkgkeixn',
tags: [
{
title: 'Material',
id: 'ewyherer'
},
{
title: 'Construction',
id: 'cchtfyjf'
}
]
},
{
title: 'Steel',
id: 'drftgycs',
tags: [
{
title: 'Surface',
id: 'sfkstewc',
tags: [
{
title: 'Polished',
id: 'vbraurff'
},
{
title: 'Coated',
id: 'sdusfgsf'
}
]
},
{
title: 'Quality',
id: 'zsasyewe'
}
]
}
]
The output I'm trying to get is this:
{
'dkgkeixn': ['Wood'],
'ewyherer': ['Wood', 'Material'],
'cchtfyjf': ['Wood', 'Construction'],
'drftgycs': ['Steel'],
'sfkstewc': ['Steel', 'Surface'],
'vbraurff': ['Steel', 'Surface', 'Polished'],
'sdusfgsf': ['Steel', 'Surface', 'Coated'],
'zsasyewe': ['Steel', 'Quality']
}
So I'm building this recursive function which is almost doing it's job, but I keep getting the wrong paths in my flat/key map:
function flatMap(tag, acc, pathBefore) {
if (!acc[tag.id]) acc[tag.id] = [...pathBefore];
acc[tag.id].push(tag.title);
if (tag.tags) {
pathBefore.push(tag.title)
tag.tags.forEach(el => flatMap(el, acc, pathBefore))
}
return acc
}
const keyMap = flatMap({ title: 'Root', id: 'root', tags}, {}, []);
console.log("keyMap", keyMap)
I'm trying to get the path until a tag with no tags and then set that path as value for the ID and then push the items 'own' title. But somehow the paths get messed up.
Check this, makePaths arguments are tags, result object and prefixed titles.
const makePaths = (tags, res = {}, prefix = []) => {
tags.forEach(tag => {
const values = [...prefix, tag.title];
Object.assign(res, { [tag.id]: values });
if (tag.tags) {
makePaths(tag.tags, res, values);
}
});
return res;
};
const tags = [
{
title: "Wood",
id: "dkgkeixn",
tags: [
{
title: "Material",
id: "ewyherer"
},
{
title: "Construction",
id: "cchtfyjf"
}
]
},
{
title: "Steel",
id: "drftgycs",
tags: [
{
title: "Surface",
id: "sfkstewc",
tags: [
{
title: "Polished",
id: "vbraurff"
},
{
title: "Coated",
id: "sdusfgsf"
}
]
},
{
title: "Quality",
id: "zsasyewe"
}
]
}
];
console.log(makePaths(tags));

Categories

Resources