Manipulating objects in an array - javascript

I am new to JavaScript and been struggling to combine objects in the same array.
Here is what I have:
var testList = [{
'taskList1': 'task1 for taskList1',
},
{
'taskList1': 'task2 for taskList1',
},
{
'taskList2': 'task1 for taskList2'
},
{
'taskList2': 'task2 for taskList2'
}]
The array below is what I really want to get from above:
var testList = [{
'taskList1': 'task1 for taskList1',
'taskList2': 'task1 for taskList2'
},
{
'taskList1': 'task2 for taskList1',
'taskList2': 'task2 for taskList2'
}]
Could anyone please help me to transform my current array into the one above?
Thank you in advance.

Your data structure is quite inefficient in this case. I'd suggest to make it better by having the same array of objects, but each object should contain itemName and belongsTo as a reference to any collection (in your case - a taskList) you may pass there.
Here's a solution to your problem with a more flexible data structure on Codepen - https://codepen.io/Inlesco/pen/dReYgd
I've also added the restructured array of tasks below as an example that's used in the Codepen above.
var testList = [{
item: 'task1',
belongsTo: 'taskList1'
},
{
item: 'task2',
belongsTo: 'taskList1'
},
{
item: 'task1',
belongsTo: 'taskList2'
},
{
item: 'task2',
belongsTo: 'taskList2'
}]
There are many ways to approach this problem. I've just added probably the simplest one.

You can use a for statement to regroup objects with the same taskList ID in one object.
And of course your need to use the right conditions for that.
But the best way is as #Denialos said, to modify your data structure.

Per my comments above to the question, your desired data structure appears to be inverted, or "inside out". Given a list of items, and a set of tasks for each item, I would expect the outer element to be the list, and the inner element to be the set of tasks.
Given that, given your (current) input data I would use:
function restructure(taskList) {
var result = {};
for (var i = 0, n = taskList.length; i < n; ++i) {
// read current item
var item = taskList[i];
var key = Object.keys(item)[0];
var value = item[key];
// update the output
result[key] = result[key] || [];
result[key].push(value);
}
return result;
}
with resulting output:
{
taskList1: [ 'task1 for taskList1', 'task2 for taskList1' ],
taskList2: [ 'task1 for taskList2', 'task2 for taskList2' ]
}
That said, your input data model is also somewhat malformed, with each array element having an unknown key. You should look at what's actually producing that data and fix that if possible.

Related

Access and extract values from doubly nested array of objects in JavaScript

I have an array of objects and within those objects is another object which contains a particular property which I want to get the value from and store in a separate array.
How do I access and store the value from the name property from the data structure below:
pokemon:Object
abilities:Array[2]
0:Object
ability:Object
name:"blaze"
1:Object
ability:Object
name:"solar-power"
How would I return and display the values in the name property as a nice string like
blaze, solar-power ?
I tried doing something like this but I still get an array and I don't want to do a 3rd loop since that is not performant.
let pokemonAbilities = [];
let test = pokemon.abilities.map((poke) =>
Object.fromEntries(
Object.entries(poke).map(([a, b]) => [a, Object.values(b)[0]])
)
);
test.map((t) => pokemonAbilities.push(t.ability));
Sample Data:
"pokemon": {
"abilities": [
{
"ability": {
"name": "friend-guard",
"url": "https://pokeapi.co/api/v2/ability/132/"
},
"ability": {
"name": "Solar-flare",
"url": "https://pokeapi.co/api/v2/ability/132/"
}
}
]
}
Then I am doing a join on the returned array from above to get a formatted string.
It just seems like the multiple map() loops can be optimized but I am unsure how to make it more efficient.
Thank you.
There is no need for a loop within loop. Try this:
const pokemon = {
abilities: [{
ability: {
name: 'friend-guard',
url: 'https://pokeapi.co/api/v2/ability/132/'
},
}, {
ability: {
name: 'Solar-flare',
url: 'https://pokeapi.co/api/v2/ability/132/'
}
}]
};
const pokemonAbilities = pokemon.abilities.map(item => item.ability.name).join(', ');
console.log(pokemonAbilities);

Filter Array Using Partial String Match in Javascript

I have an array of objects where the value I need to filter on is buried in a long string. Array looks like:
{
"data": {
"value": "{\"cols\":[\"parent_sku\"],\"label\":\"Style\",\"description\":\"Enter Style.\",\"placeholderText\":\"Style 10110120103\"}",
"partnerId": 1
}
},
So if I wanted to grab all the partnerId objects where value includes parent_sku how would I do that?
console.log(data.value.includes('parent_sku') returns cannot read property 'includes' of null.
EDIT:
Didn't think this mattered, but judging by responses, seems it does. Here's the full response object:
Response body: {
"data": {
"configurationByCode": [
{
"data": {
"value": "{\"cols\":[\"parent_sku\"],\"label\":\"Style\",\"description\":\"Enter Style.\",\"placeholderText\":\"Style 10110120103\"}",
"partnerId": 1
}
}
I'm passing that into a re-usable function for filtering arrays:
const parentSkuPartners = filterArray(res.body.data.configurationByCode, 'parent_sku');
Function:
function filterArray(array, filterList) {
const newList = [];
for (let i = 0; i < array.length; i += 1) {
console.log('LOG', array[i].data.value.includes('parent_sku');
}
}
The problem is somewhere else. The code you've tried should work to find if a value contains a string – I've added it the snippet below and you'll see it works.
The issue is how you are accessing data and data.value. The error message clearly states that it believes that data.value is null. We would need to see the code around it to be able to figure out what the problem is. Try just logging to console the value of data before you run the includes function.
const data = {
"value": "{\"cols\":[\"parent_sku\"],\"label\":\"Style\",\"description\":\"Enter Style.\",\"placeholderText\":\"Style 10110120103\"}", "partnerId": 1
};
console.log('includes?', data.value.includes('parent_sku'));
You can use data.value.includes('parent_sku') as you have suggested. The issue here is that your object is nested inside an unnamed object.
try:
"data": {
"value": "{\"cols\":[\"parent_sku\"],\"label\":\"Style\",\"description\":\"Enter Style.\",\"placeholderText\":\"Style 10110120103\"}",
"partnerId": 1
}
The problem was some of the values for value were null. Adding an extra conditional fixed it:
if (array[i].data.value !== null) {
Use lodash includes, and lodash filter like
let configurationByCode = [{
data: {
value: {
cols:["parent_sku"],
label:"Style",
description:"Enter Style.",
placeholderText:"Style 10110120103"
},
"partnerId": 1
}
}, {
data: {
value: {
cols:["nothing"],
label:"Style",
description:"Enter Style.",
placeholderText:"Style 10110120103"
},
"partnerId": 2
}
}];
let wantedData = _.filter(configurationByCode, (config) => {
return _.includes(config.data.value.cols, 'parent_sku');
});
console.log( wantedData );
https://jsfiddle.net/76cndsp2/

Removing duplicates elements with conditionality

I have an array of objects that look like this:
[
{ project: "test1", date: "8/14/2018" },
{ project: "test1", date: "8/15/2018" },
{ project: "test2", date: "8/14/2018" }
]
I want to remove duplicate objects based on the project name, BUT, keep the one with the most recent date.
So my final array would like this:
[
{ project: "test1", date: "8/15/2018" },
{ project: "test2", date: "8/14/2018" }
]
I've come up with a disgruntled recursive solution that I'm unhappy with.
Looking for suggestions on a painless way to do this.
The approach I generally take for problems like this is to maintain a "dictionary" object to track uniqueness while iterating through, then extract the final result from that result. reduce is the go-to tool for creating one value from multiple values:
const dict = objects.reduce((result, item) => {
const currentForProject = result[item.project];
const isMostRecent =
!currentForProject
|| new Date(item.date) > new Date(currentForProject.date);
if (isMostRecent) {
result[item.project] = item;
}
return result;
}, {});
const mostRecents = Object.values(dict);
I will propose the general algorithm to solve your task but the implementation is up to you.
1) sort the array based on date field;
2) create an empty Set for storing project names and empty array for the result;
3) iterate over the sorted array and check:
3.1) if the Set does not contain current project name, then:
3.2) add the project name to the Set and add current item to your result
array;

How do I iterate through an array that is nested inside an object that is in turn nested in an array?

What I want to accomplish:
To retrieve all licenseTypes (digger and shovler) so that I can insert them in a header div.
To retrieve the respective licenseTypes' subLicenses to be used in a subheading (or maybe body) depending on the view.
My array looks like this:
const licenseType = [
{
diggerLisense: [
"Shallow Digger",
"Deep Digger"
]
},
shoverlerLicense: [
"Poop shovler",
"Grass shovler"
]
}
]
So basically, I have this structure:
licenseType > subLicenseType > subSubLicenseType
I specifically decided on this nested order for three reasons:
To map over the licenseTypes (digger and shovler) so that it can be used in a card Heading
To map over the respective subLicenseTypes (Shallow Digger, Deep Digger, Poop shover, Grass shovler) to be used in the same cards subheading. For some reason I think it's easier to handle state this way.
To keep all license types in a neat object structure that can be exported/imported throughout my project.
Any help or accusations is greatly appreciated here. BTW, I have searched other questions and nothing exactly like the structure I have described here.
Edit: I want to thank the overwhelming and swift response that you've all offered. I'm amazed at how quickly you people help. This is my first question on here and I can't believe the speed of the response.
I am currently working the suggestions that were offered including the one that suggests a different format. I will post a fiddle of the end result later when I'm done. Thanks all you members of the stackoverflow community
You can iterate the licenseType with Array.map(). For each object get the first entry, and return whatever you want to display:
const licenseType = [{"diggerLisense":["Shallow Digger","Deep Digger"]},{"shoverlerLicense":["Poop shovler","Grass shovler"]}];
const result = licenseType.map((o) => {
const [license, subLicenses] = Object.entries(o)[0];
return `
<h1>${license}</h1>
<ul>
${subLicenses.map((s) => `<li>${s}</li>`).join('\n')}
</ul>
`;
});
demo.innerHTML = result.join('\n');
<div id="demo"></div>
However, having a changing key in an object, complicates it needlessly. I suggest a slightly different format:
{
license: 'digger',
sub: ['Shallow Digger', 'Deep Digger']
}
const licenseType = [{ "license": "digger", "sub": ["Shallow Digger","Deep Digger"]},{ "license": "shoverler", sub: ["Poop shovler","Grass shovler"]}];
const result = licenseType.map(({ license, sub }) => `
<h1>${license}</h1>
<ul>
${sub.map((s) => `<li>${s}</li>`).join('\n')}
</ul>
`);
demo.innerHTML = result.join('\n');
<div id="demo"></div>
Try this:
licenseType.forEach(element => {
element[Object.keys(element)[0]].forEach(subTypes => {
console.log(subTypes);
})
});
Given your current data set, you can do something like this.
However, it would be easier if your top level data structure was an object, not an array.
const licenseType = [
{
diggerLisense: [
"Shallow Digger",
"Deep Digger"
]
},
{
shoverlerLicense: [
"Poop shovler",
"Grass shovler"
]
}
];
const getLicenses = () => licenseType.map(license => Object.keys(license)[0]);
const getData = (toFind) => licenseType.find(license => Object.keys(license)[0] === toFind);
const getSubtypes = (license) => {
const data = getData(license);
if (data) {
subTypes = data[license];
}
return subTypes;
};
console.log(getLicenses());
console.log(getSubtypes('shoverlerLicense'));
LicenseType is an array So you can access the license type like licenseType[i] where it represents the element of the array. for sub license type use
sublicensetype = []
for (i = 0; i < licenseType.length; i++) {
for ( var k in licenseType[i]) sublicenseType.push(k)
}
Try it like this fiddle:
licenseType.forEach(function (type) {
console.log('type', type);
Object.keys(type).forEach(function (typeKey) {
console.log('typeKey',typeKey);
console.log('typeValues',type[typeKey]);
});
});
Also, you have a syntax error in your initial array:
const licenseType = [
{
diggerLisense: [
"Shallow Digger",
"Deep Digger"
]
},
{ //this bracket was missing
shoverlerLicense: [
"Poop shovler",
"Grass shovler"
]
}
]

Order changed after distinct() : RethinkDb Javascript

I am working with the Reql, the problem i am facing is that i need to filter the same plucked values in correct order.
After pluck and distinct() apply, value are correct but not in correct order, their order lost.
Sample Query
r.db('DB').table("heroes").orderBy('createdAt')
.pluck({'loc':['coordinates']})
.distinct()
Can anyone help me to modify the query, so that it return data in correct order.
Thanks for your time.
After looking for another workaround i posted question here (thanks to #trincot) to get work done in javascript instead to handle duplicate array of lat longs, by duplicating solution of this sample array. Getting distinct result and the order is maintained.
var array = [
{ person: { amount: [1,1] } },
{ person: { amount: [1,1] } },
{ person: { amount: [2,1] } },
{ person: { amount: [1,2] } },
{ person: { amount: [1,2] } }
];
var result = [...new Map(array.map( o => [JSON.stringify(o), o])).values()];
console.log(result);
In case of anyone who might get help.Cheers.

Categories

Resources