Setting array keys dynamically based on length - javascript

Given an array in this format:
[
[{
name: "name",
value: "My-name"
},
{
name: "qty",
value: "1"
},
{
name: "url",
value: "test.com"
},
{
name: "comment",
value: "my-comment"
}
],
[{
name: "name",
value: "My-name2"
},
{
name: "qty",
value: "3"
},
{
name: "url",
value: "test2.com"
}
],
[{
name: "name",
value: "My-name3"
},
{
name: "qty",
value: "1"
},
{
name: "url",
value: "test3.com"
},
{
name: "comment",
value: "my-comment3"
}
]
]
I'm looking to switch that to:
[
[
{ name: "My-name" },
{ qty: "1" },
{ url: "test.com" },
{ comment: "my-comment", }
],[
{ name: "My-name2" },
{ qty: "3" },
{ url: "test2.com",
],[
{ name: "My-name3", },
{ qty: "1", },
{ url: "test3.com", },
{ comment: "my-comment3", }
]
]
In other words, swapping out the array keys but maintaining the object structure within each array element.
I've tried looping over each element and can swap the keys out using something like:
newArray[iCount][item.name] = item.value;
However I'm then struggling to preserve the object order. Note that the comment field may or may not appear in the object.

With Array.map() function:
var arr = [
[{name:"name",value:"My-name"},{name:"qty",value:"1"},{name:"url",value:"test.com"},{name:"comment",value:"my-comment"}],
[{name:"name",value:"My-name2"},{name:"qty",value:"3"},{name:"url",value:"test2.com"}],
[{name:"name",value:"My-name3"},{name:"qty",value:"1"},{name:"url",value:"test3.com"},{name:"comment",value:"my-comment3"}]
],
result = arr.map(function(a){
return a.map(function(obj){
var o = {};
o[obj.name] = obj.value
return o;
});
});
console.log(result);

Check my moreBetterOutput value. I think will be better.
If you still need a result like your example in the question then you can check output value.
const input = [
[
{
name:"name",
value:"My-name"
},
{
name:"qty",
value:"1"
},
{
name:"url",
value:"test.com"
},
{
name:"comment",
value:"my-comment"
}
],
[
{
name:"name",
value:"My-name2"
},
{
name:"qty",
value:"3"
},
{
name:"url",
value:"test2.com"
}
],
[
{
name:"name",
value:"My-name3"
},
{
name:"qty",
value:"1"
},
{
name:"url",
value:"test3.com"
},
{
name:"comment",
value:"my-comment3"
}
]
]
const output = input.map(arr => arr.map(obj => ({[obj.name]: obj.value})))
const moreBetterOutput = output.map(arr => arr.reduce((acc, item, index) => {
acc[Object.keys(item)[0]] = item[Object.keys(item)[0]];
return acc;
}, {}) )
//console.log(output);
console.log(moreBetterOutput);

Another map function:
const result = array.map( subarray =>
Object.assign(...subarray.map( ({name, value}) => ({ [name] : value }) ))
);

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));

How to get all possible ways of passing the quiz

The quiz is implemented in such a way that questions are displayed depending on the user's choice. I need to implement the testing functionality of the questionnaire. After passing in the console should have the same structure as I have provided below. Now my script produces a slightly different structure, not the same as in the example. Example of my code:
const questions = [
{
id: "1",
question: "q1",
answer_1: {
text: "a1",
next_question: "2",
},
answer_2: {
text: "a2",
next_question: "3",
},
},
{
id: "2",
question: "q2",
answer_1: {
text: "a1/a2",
next_question: "",
},
},
{
id: "3",
question: "q3",
answer_1: {
text: "a1",
next_question: "",
},
answer_2: {
text: "a2",
next_question: "4",
},
},
{
id: "4",
question: "q4",
answer_1: {
text: "a1/a2",
next_question: "",
},
},
];
const newQuestionObj = {};
const getAllPath = (arr) => {
const treeStructure = arr.forEach((item) => {
newQuestionObj[item.id] = {
...item,
children: [
...Object.keys(item)
.filter((k) => k.includes("answer"))
.map((k) => ({ ...item[k] })),
],
};
});
const createBranches = ({ question, children }) =>
children.map(({ text, next_question }) =>
next_question.length === 0
? { [question]: text }
: createBranches(newQuestionObj[next_question]).map((obj) => ({
[question]: text,
...obj,
}))
);
return createBranches(newQuestionObj[arr[0].id]);
};
let result = {
path: {
list: getAllPath(questions),
},
};
console.log(result);
Desired result to get:
{
"paths":{
"list":[
[
{
"q1":"a1"
},
{
"q2":"a1/a2"
}
],
[
{
"q1":"a2"
},
{
"q3":"a1"
}
],
[
{
"q1":"a2"
},
{
"q3":"a2"
},
{
"q4":"a1/a2"
}
]
]
}
}

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);

How to convert array of objects into enum like key value pair in javascript?

I have an array
const a = [
{ name: "read-web-courses" },
{ name: "example" },
{ name: "t_gql" },
{ name: "ddddd" },
];
I am trying it to reduce it to the below given output , However I am stuck
Output
{0:"read-web-courses",1:"example",2:"t_gql",3:"ddddd"}
You could map the wanted property and assign the pairs to the object.
const
array = [{ name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }],
result = Object.assign({}, array.map(({ name }) => name));
console.log(result);
You can use Array.reduce like below.
const a = [
{ name: "read-web-courses" },
{ name: "example" },
{ name: "t_gql" },
{ name: "ddddd" },
];
const convert = arr => (
arr.reduce((total, value, index) => {
total[index] = value.name;
return total;
}, {})
)
console.log(convert(a));
This is accomplished using Array#reduce, where you can use the index from the reduce callback as the key of the new object:
const a = [ { name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }];
const res = a.reduce((r, o, i) => {
r[i] = o.name;
return r;
}, {});
console.log(res);
Also one more approach using Object#fromEntries and Array#map, where each object is converted to an array of key, value pairs:
const a = [ { name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }];
const res = Object.fromEntries(a.map((o, i) => [i, o.name]));
console.log(res)

Transforming array of objects based upon key - javascript

I am trying to figure out the most efficient method for reducing an array of objects based upon a unique key (key/values are dynamically returned in this case). I've tried to a combination of different methods using concat, map, or filter but haven't had much luck.
Original array of objects:
[
{
key: "Name",
value: "John"
},
{
key: "Company",
value: "Acme"
},
{
key: "Name",
value: "Jack"
},
{
key: "Name",
value: "Matt"
},
{
key: "Last",
value: "Test"
}
]
Desired Array:
[
{
key: "Name",
values: [
"John",
"Jack",
"Matt"
]
},
{
key: "Company",
values: [
"Acme"
]
},
{
key: "Last",
values: [
"Test"
]
}
]
Prob other ways, but a simple for loop would suffice:
const data = [{
key: "Name",
value: "John"
},
{
key: "Company",
value: "Acme"
},
{
key: "Name",
value: "Jack"
},
{
key: "Name",
value: "Matt"
},
{
key: "Last",
value: "Test"
}
]
let result = {}
for (const i in data) {
result[data[i].key] = {
key: data[i].key,
values: [
...result[data[i].key] ? result[data[i].key].values : [],
data[i].value
]
}
}
console.log(Object.values(result))
You can use reduce to build a new object using name as the keys, and then use Object.values to create the output you need from the object:
const data = [
{ key: "Name", value: "John" },
{ key: "Company", value: "Acme" },
{ key: "Name", value: "Jack" },
{ key: "Name", value: "Matt" },
{ key: "Last", value: "Test" }
];
const out = Object.values(data.reduce((acc, { key, value }) => {
// If the key doesn't exist on the object, add it
// and initialise the value object
acc[key] = acc[key] || { key, values: [] };
// Push the value from the current iteration
// into the values array
acc[key].values.push(value);
// Return the accumulator for the next iteration
return acc;
}, {}));
console.log(out);
I think reduce is the best solution here :)
const initialArray = [
{
key: "Name",
value: "John"
},
{
key: "Company",
value: "Acme"
},
{
key: "Name",
value: "Jack"
},
{
key: "Name",
value: "Matt"
},
{
key: "Last",
value: "Test"
}
];
const result = initialArray.reduce((acc, obj) => {
/* try to find object in the result array
returns index or -1 if object is missing
*/
const existingIndex = acc.findIndex(item => item.key === obj.key);
if (existingIndex > -1) {
/* object already exists, update its values array */
acc[existingIndex].values.push(obj.value);
return acc;
} else {
/* the key is first encountered, create an object in the result array */
acc.push({
key: obj.key,
values: [obj.value],
});
return acc;
}
}, []); // [] - default value is an empty array
console.log(result);

Categories

Resources