I have to map a composed array - javascript

I have an array I need to get all the tasks that have the same record Id in an array
workspaces=[{recordId:1,tasks:[{title:'me'},{title:'we'}]},{recordId:2,tasks:[{title:'hi'},{title:'it'}]},{recordId:1,tasks:[{title:'they',{title:'she'}]}]
the final result will be like:[[recordId:1,tasks:[{title:'me'},{title:'we'},{title:'they',{title:'she'}]],[recordId:2,tasks:[{title:'hi'},{title:'it'}]]]
i used groupBy from lodash but i did get a separate arrays anyone have any idea how to implement that.

A possible solution could be a two step approach by
collecting items for a certain group
render the array in the wanted format.
This approach features a Map and uses Array.from for getting the wanted result.
var workspaces = [{ recordId: 1, tasks: [{ title: 'me' }, { title: 'we' }] }, { recordId: 2, tasks: [{ title: 'hi' }, { title: 'it' }] }, { recordId: 1, tasks: [{ title: 'they' }, { title: 'she' }] }],
grouped = Array.from(
workspaces.reduce((m, { recordId, tasks }) =>
m.set(recordId, [...(m.get(recordId) || []), ...tasks]), new Map),
([recordId, tasks]) => ({ recordId, tasks })
);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Nina Scholz solution is more sophisticated, but harder to read.
You can achieve the same like this:
const workspaces= [
{recordId: 1, tasks: [{title:'me'}, {title:'we'}] },
{recordId: 2, tasks: [{title:'hi'}, {title:'it'}] },
{recordId: 1, tasks: [{title:'they'}, {title:'she'}] }
]
const workspacesById = []
workspaces.forEach(w => {
const idx = workspacesById.findIndex(item => item.recordId === w.recordId)
if (idx > -1) {
workspacesById[idx].tasks = [...workspacesById[idx].tasks, ...w.tasks]
} else {
workspacesById.push(w)
}
})
console.log(workspacesById)

I think this is close to what you want
const arr = [
{ recordId: 1, tasks: [{ title: 'me' }, { title: 'we' }] },
{ recordId: 2, tasks: [{ title: 'hi' }, { title: 'it' }] },
{ recordId: 2, tasks: [{ title: 'f' }, { title: 'e' }] },
{ recordId: 2, tasks: [{ title: 'hi' }, { title: 'it' }] },
];
const result = arr.reduce((result, item) => {
if (result[item.recordId]) {
const prevTasks = result[item.recordId];
result[item.recordId].tasks = prevTasks.concat(item.tasks);
} else {
result[item.recordId] = item.tasks;
}
return result;
}, {});
The result will be
{
"1": [
{
"title": "me"
},
{
"title": "we"
}
],
"2": [
{
"title": "hi"
},
{
"title": "it"
}
]
}

Here is your result
let result = [];
for(let i=0; i<workspaces.length; i++) {
let recordFound = false;
if (result.length > 0) {
for(let j=0; j<result.length ; j++) {
if(workspaces[i].recordId === result[j].recordId) {
result[j].tasks = [...result[j].tasks, ...workspaces[i].tasks];
recordFound = true;
}
}
}
if (!recordFound) {
result.push(workspaces[i]);
}
}
console.log(result); //your expected result

Related

Being able to remove duplicate keys from an array of objects

I have a question about how I can delete the existing elements, for example, in my case "Tallas" is repeated, could you please help me? Thank you very much to those who are willing to help me to solve this problem
const data =
[ { atributos: { Tallas: [{ id: 0, name: 'XS' }, { id: 1, name: 'S' }] }}
, { atributos: { Calzado: [{ id: 0, name: '10' }, { id: 1, name: '9.5' }] }}
, { atributos: { Tallas: [{ id: 0, name: 'XS' }] }}
]
The idea is to have this json format with the last "Tallas" since it is the last one that I added through my dynamic form.
const expected =
[{ atributos: { Calzado: [{ id: 0, name: '10' }, { id: 1, name: '9.5' }] }}
, { atributos: { Tallas: [{ id: 0, name: 'XS' }] }}
]
How do I do this is there a way to do it, I've tried with filter plus the findindex but I can't get to eliminate the repetition of the json res= new.filter((arr, index, self) => index === self.findIndex( (t) => (t.attributes === arr.attributes )))
To unique the array of objects, we can use the Javascript Set module, if the array has complex nested objects, we can stringify each object before creating new Set data. this below function will unique the array of complex objects.
function unique_array(array = []) {
const newSetData = new Set(array.map((e) => JSON.stringify(e)));
return Array.from(newSetData).map((e) => JSON.parse(e));
}
this is a function that takes an array and return the same array but delete every duplicated item
function removeDuplicates(arr) {
return arr.filter((item,
index) => arr.indexOf(item) === index);
}
I didn't understant the part written in spanish so I hope this is what you are looking for
This is a solution specific to your question. this is not a generic solution.
const data = [
{
atributos: {
Tallas: [
{ id: 0, name: "XS" },
{ id: 1, name: "S" },
],
},
},
{
atributos: {
Calzado: [
{ id: 0, name: "10" },
{ id: 1, name: "9.5" },
],
},
},
{
atributos: {
Tallas: [
{ id: 0, name: "XS" },
{ id: 1, name: "S" },
],
},
},
];
function uniqueArray(array) {
const resultObject = array.reduce((acc, eachValue) => {
let keys = Object.keys(eachValue.atributos);
keys.forEach((eachKey) => {
if (!acc[eachKey]) {
acc[eachKey] = [];
}
let list = eachValue["atributos"][eachKey].map(
(each) => each.id + "-" + each.name
);
acc[eachKey].push(...list);
});
return acc;
}, {});
const resultArray = Object.keys(resultObject).reduce((acc, each) => {
let setData = Array.from(new Set(resultObject[each]));
acc.push({
atributos: {
[each]: setData.map((e) => {
return { id: e.split("-")[0], name: e.split("-")[1] };
}),
},
});
return acc;
}, []);
return resultArray;
}
const result = uniqueArray(data)
console.log("result ", JSON.stringify(result, null, 2));

Return last value with recursion - Javascript

Hi all I have following data:
const section = {
fileds: [
{ id: "some Id-1", type: "user-1" },
{
child: [
{ id: "some Id-2", type: "user-2" },
{ fileds: [{ id: "kxf5", status: "pending" }] },
{ fileds: [{ id: "ed5t", status: "done" }] }
]
},
{
child: [
{ id: "some Id-3", type: "teacher" },
{ fileds: [{ id: "ccfr", status: null }] },
{ fileds: [{ id: "kdpt8", status: "inProgress" }] }
]
}
]
};
and following code:
const getLastIds = (arr) =>
arr.flatMap((obj) => {
const arrayArrs = Object.values(obj).filter((v) => Array.isArray(v));
const arrayVals = Object.entries(obj)
.filter(([k, v]) => typeof v === "string" && k === "id")
.map(([k, v]) => v);
return [...arrayVals, ...arrayArrs.flatMap((arr) => getLastIds(arr))];
});
console.log(getLastIds(section.fileds));
// output is (7) ["some Id-1", "some Id-2", "kxf5", "ed5t", "some Id-3", "ccfr", "kdpt8"]
My code doing following, it printing in new array all ids.
It's working but I don't need all ids.
I need to return only last id in array and I should use recursion.
The output should be
(4) [" "kxf5", "ed5t", "ccfr", "kdpt8"]
P.S. here is my code in codesandbox
Is there a way to solve this problem with recursion? Please help to fix this.
You can do it with reduce.
function getLastIds (value) {
return value.reduce((prev, cur) => {
if (cur.id) {
return [ ...prev, cur.id ];
} else {
let key = ('child' in cur) ? 'child' : 'fileds';
return [ ...prev, ...getLastIds (cur[key]) ]
}
}, []);
}
You could check if a certain key exists and take this property for mapping id if status exists.
const
getValues = data => {
const array = Object.values(data).find(Array.isArray);
return array
? array.flatMap(getValues)
: 'status' in data ? data.id : [];
},
section = { fileds: [{ id: "some Id-1", type: "user-1" }, { child: [{ id: "some Id-2", type: "user-2" }, { fileds: [{ id: "kxf5", status: "pending" }] }, { fileds: [{ id: "ed5t", status: "done" }] }] }, { child: [{ id: "some Id-3", type: "teacher" }, { fileds: [{ id: "ccfr", status: null }] }, { fileds: [{ id: "kdpt8", status: "inProgress" }] }] }] },
result = getValues(section);
console.log(result);

Modify array to stop object from being nested

I have an example array
const array = [
{ obj: [{ fields: { title: 'titleValue1' } }, { fields: { title: 'titleValue2' } }] },
{ obj: [{ fields: { title: 'titleValue3' } }, { fields: { title: 'titleValue4' } }] },
]
I'm looking to modify the array to:
const modifiedArray = [
{ obj: [{ title: 'titleValue1' }, { title: 'titleValue2' }] },
{ obj: [{ title: 'titleValue3' }, { title: 'titleValue4' }] },
]
So when I loop over the modified array I can call 'obj.title' instead of 'obj.fields.title'
I think this can be achieved using .map. So far I have tried:
const ammendedArray = array.map(item => ({ ...item, title: item.map(e => e.fields) }))
But returning 'item.map is not a function'
Any help with this would be much appreciated.
In your code you are trying to use map for an item in the top level array. Which is like this for the first item,
{ obj: [{ fields: { title: 'titleValue1' } }, { fields: { title: 'titleValue2' } }] }
As you can see item is an object. You can not map through an object. What you can do is map through item.obj
const ammendedArray = array.map(item => ({ ...item, title: item.obj.map(e => e.fields) }))
But it will not solve your problem you will get a wrong array of objects like this,
[
{
obj: [{ fields: { title: 'titleValue1' } }, { fields: { title: 'titleValue2' } }],
title: [{ title: 'titleValue1' }, { title: 'titleValue2' }]
},
...
]
You will have to update the obj key instead. What you need to do is the following,
const array = [
{ obj: [{ fields: { title: 'titleValue1' } }, { fields: { title: 'titleValue2' } }] },
{ obj: [{ fields: { title: 'titleValue3' } }, { fields: { title: 'titleValue4' } }] },
]
const res = array.map((item) => {
return {
obj: item.obj.map(i => {
return i.fields
})
};
});
console.log(res);
I could reach to that like this :)
const array = [
{ obj: [{ fields: { title: 'titleValue1' } }, { fields: { title: 'titleValue2' } }] },
{ obj: [{ fields: { title: 'titleValue3' } }, { fields: { title: 'titleValue4' } }] },
]
// pass a function to map
const map1 = array.map((x)=>{
const filedsArray = [...x.obj]
x.obj = []
filedsArray.forEach((y)=>{
x.obj.push({title:y.fields.title})
})
return x
})
console.log(map1);

Transform object data with recursive

I try to transform data with recursive but I can't, I'm very newbie for recursive please help me
Is it need to do with recursive or not what you guy think,
Please help me
(sorry for my english)
This is my data
const mock = [
{ $: { id: '001' } },
{
$: { id: '002' },
question: [{
$: { id: 'r001' },
prompt: 'some-r001',
choices: [{
question: [
{
$: { id: 'r001-1' },
prompt: 'some-r001-1',
choices: [{
question: [{
$: { id: 'r001-1-1' },
prompt: 'some-r001-1-1',
choices: [""],
}]
}]
},
{
$: { id: 'r001-2' },
prompt: 'some-r001-2',
choices: [""],
},
]
}]
}]
}
]
I want to transform to this
const result = {
'r001': {
prompt: 'some-r001',
next: ['r001-1', 'r001-2'],
},
'r001-1': {
prompt: 'some-r001-1',
next: ['r001-1-1'],
}
'r001-1-1': {
prompt: 'some-r001-1-1',
next: [],
},
'r001-2': {
prompt: 'some-r001-2',
next: [],
},
}
You could flat the array in an object by iterating and getting the parts by a recursive call of the function.
const
getFlat = (array, parent = []) => array.reduce((r, { question, choices, prompt, $: { id } = {} }) => {
if (question) return { ...r, ...getFlat(question, parent) };
if (choices) {
parent.push(id);
var next = [];
return { ...r, [id]: { prompt, next }, ...getFlat(choices, next) };
}
return r;
}, {}),
mock = [{ $: { id: '001' } }, { $: { id: '002' }, question: [{ $: { id: 'r001' }, prompt: 'some-r001', choices: [{ question: [{ $: { id: 'r001-1' }, prompt: 'some-r001-1', choices: [{ question: [{ $: { id: 'r001-1-1' }, prompt: 'some-r001-1-1', choices: [""] }] }] }, { $: { id: 'r001-2' }, prompt: 'some-r001-2', choices: [""] }] }] }] }],
result = getFlat(mock);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

push line strings to array of object

i want to push the data retreived into an array but it only push into the first object.
const arr = [{ name: 'name1', item: [] }, { name: 'name2', item: [] }];
routes.forEach((elementRoute) => {
const { methods } = elementRoute;
for (const m in methods) {
let { title } = methods[m];
arr[0].item.push({
name: title,
request: { method: m,},
});
}
});
my routes array is like this :
[
{
methods: {
get: {
title: 'get users',
},
},
}
];
It only push into the first object of the item array.This is the result i actually want to get :
[
{
"name": "name1",
"item": [
{ "name": "get users", "request": { "method": "get" } } }
]
},
{
"name": "name2",
"item": [
{ "name": "get users", "request": { "method": "get" } } }
]
}
]
You need to iterate arr as well for getting all items filled.
const
arr = [{ name: 'name1', item: [] }, { name: 'name2', item: [] }],
routes = [{ methods: { get: { title: 'get users' } } }, { methods: { get: { title: 'get user id' }, delete: {} } }, ];
arr.forEach(({ item }) =>
routes.forEach(({ methods }) => {
for (const method in methods) {
let { title: name = 'Not specified' } = methods[method];
item.push({ name, request: { method } });
}
})
);
console.log(arr);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources