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;
Related
I have a table that is dynamically generated using PHP and a MySQL table/database... I also have figured out how to use filters. The problem is that it only lets you use one filter at a time... Here is a screenshot of what I mean: screenshot
You can only filter by description or by date... not both.
Is there some way to do this? I can't really provide you any HTML/JavaScript code as you won't see anything because the table data comes from a database but let me know if you need any more detail...
Thanks!
If I understood your question properly, you can do something like this:
Let's assume we have an array of objects
const data = [
{
id: 0,
date: '1609084588132',
description: 'something'
},
{
id: 1,
date: '1609087588132',
description: 'anything'
},
{
id: 2,
date: '1609087588132',
description: 'anything'
}
]
And to filter this array by two properties, you can do something like:
const filteredData = data.filter((item) => {
if (item.date > 'some date' && item.description.includes('anyth')) {
return true;
}
return false;
});
console.log(filteredData)
I think you got an idea, we filtered the array above with two conditions: id must be bigger than 0 and description string must contain 'anyth'.
I want to sort a JSON array based on time value in a subarray with the key names of the subarrays being named uniquely.
I'm searching for the method to access key, value update_time of every element in Products so I can use that value in a sorting script.
I have tried sorting the array but can not determine how to access the key, values of the subarrays
Expected behavior should be that every unique_keyname_# element is available for sorting and is sorted for further processing in JavaScript. Ultimately with the newest unique_keyname_# as the first element in a list, based on the update_time key.
var obj = {
"company": {
"department_1": {
"Products": {
"unique_keyname_1": {
"product_owner": "co-worker-1",
"update_time": "unix_timestamp_1"
},
"unique_keyname_5": {
"product_owner": "co-worker-4",
"update_time": "unix_timestamp_45"
},
"unique_keyname_8": {
"product_owner": "co-worker-2",
"update_time": "unix_timestamp_5"
}
}
},
"department_2": {
"Products": {
"unique_keyname_3": {
"product_owner": "co-worker-1",
"update_time": "unix_timestamp_21"
},
"unique_keyname_6": {
"product_owner": "co-worker-2",
"update_time": "unix_timestamp_7"
},
"unique_keyname_4": {
"product_owner": "co-worker-3",
"update_time": "unix_timestamp_75"
}
}
}
}
}
I solved the issue by writing an intermediate script in python which makes the API response a valid array. From there it was fairly easy to sort the data.
Thanks for the replies confirming the data itself was deliverd to me in an inappropriate format!
regards
In your example, there are no arrays.
Anyway, in Javascript you can access a node using . like:
obj.company.department_1.Products.unique_keyname_1
Or using [] which gives you more freedom to use costume fields
obj["company"]["department_1"]["Products"]["unique_keyname_1"]
// can also be more dynamic as:
obj["company"]["department_"+ department_counter]["Products"]["unique_keyname_" + keyname_counter]
Is there a possibility that you will change the structure of your JSON? to make it more manangeable ?
if so, i would recommend the folowing structure:
var products = [
{
department: 'SomeDepartment',
productName: 'Something',
productOwner: 'Someone',
update_time: 'Sometime'
}
]
Then you can sort the array easy using Array.sort()
for the sort topic use this : Sort array of objects by string property value
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.
So I have the following object structure:
const SamplePalette = {
id: 1,
name: "Sample Palette",
description: "this is a short description",
swatches: [
{
val: "#FF6245",
tints: ["#FFE0DB", "#FFA797"],
shades: ["#751408", "#C33F27"]
},
{
val: "#FFFDA4",
tints: ["#FFFFE1"],
shades: ["#CCCB83"]
},
{
val: "#BFE8A3",
tints: ["#E7FFD7"],
shades: ["#95B77E"]
}
]
}
Let's imagine that this object is managed by the state of my app like this:
this.state = {
currentPalette: SamplePalette,
}
My question is how would I go about updating the val property of a given swatch object in the swatches array? Or more generally - how do I only update pieces of this object?
I tried using the update helper as well as to figure out how Object.assign() works, however I've been unsuccessful and frankly can't really grasp the syntax by just looking at examples.
Also, since I'm going to be modifying this object quite a lot, should I look into maybe using Redux?
[EDIT]
I tried #maxim.sh suggestion but with no success:
this.setState(
{ currentPalette: {...this.state.currentPalette,
swatches[0].val: newValue}
})
Consider you have new new_swatches
I think the clearer way is to get array, update it and put back as:
let new_swatches = this.state.currentPalette.swatches;
new_swatches[0].val = newValue;
this.setState(
{ currentPalette:
{ ...this.state.currentPalette, swatches: new_swatches }
});
Also you have : Immutability Helpers or https://github.com/kolodny/immutability-helper
Available Commands
{$push: array} push() all the items in array on the target.
{$unshift: array} unshift() all the items in array on the target.
{$splice: array of arrays} for each item in arrays call splice() on the target with the parameters provided by the item.
{$set: any} replace the target entirely.
{$merge: object} merge the keys of object with the target.
{$apply: function} passes in the current value to the function and updates it with the new returned value.
I have an array with nested array
I want the data to append in a new array.
For the data extraction or filtration what method's i have to use, using library such as lodash
DATA
[
[
{
_id: 588d9b8a608f2a66c298849f,
email: 'sd#',
password: '$2a$10$6..L3c3tANi6ydt9gZbc1O6prPfUd3RB.ner5lilxRyEwo1lPsSoC',
isJobSeeker: true,
__v: 0,
lastName: 'shrestha',
firstName: 'manish',
isSeeker: true
}
],
[
{
_id: 588dbb4f7a48ce0d26cb99fd,
jobId: [Object],
seekerId: 588d9b8a608f2a66c298849f,
employerId: 588d7d6c0ec4512feb819825,
__v: 0,
}
]
]
REQUIRED DATA
[
{
_id: 588d9b8a608f2a66c298849f,
email: 'sd#',
password: '$2a$10$6..L3c3tANi6ydt9gZbc1O6prPfUd3RB.ner5lilxRyEwo1lPsSoC',
isJobSeeker: true,
__v: 0,
lastName: 'shrestha',
firstName: 'manish',
isSeeker: true
},
jobId: [{}, {}, {}] // ARRAY WITH OBJECTS
]
also i want to change the jobId key to other key of custom string as jobs
Following is my attempt:
console.log('Data filteration', data);
const filteredData = [];
filteredData.push(data[0][0]);
data[1].forEach((i) => {
filteredData[0].jobs = i.jobId
});
console.log('filteredData', filteredData);
First you should clean you data to have a better structure.
[
[
{ ... }
],
[
{ ... }
]
]
In this datastructure, its difficult to understand what does inner arrays signify. Instead you should use an object. That would define the purpose of array and make your code more readable.
var data=[[{_id:"588d9b8a608f2a66c298849f",email:"sd#",password:"$2a$10$6..L3c3tANi6ydt9gZbc1O6prPfUd3RB.ner5lilxRyEwo1lPsSoC",isJobSeeker:!0,__v:0,lastName:"shrestha",firstName:"manish",isSeeker:!0}],[{_id:"588dbb4f7a48ce0d26cb99fd",jobId:["test","test1"],seekerId:"588d9b8a608f2a66c298849f",employerId:"588d7d6c0ec4512feb819825",__v:0}]];
var cleanedData = {
userData: data[0],
userJobMap: data[1],
}
var result = cleanedData.userData.reduce(function(p,c){
if(c.isJobSeeker){
var job = cleanedData.userJobMap.filter(x=> x.seekerId === c._id);
// To copy object and not reference
var t = Object.assign({}, c, { jobId: job[0].jobId });
p.push(t)
}
return p
}, [])
console.log(result)
References
Array.map is a tool that iterates over all elements and return different value say a single property of return double value of all numbers in array. Note, this will yield an array of same size.
Array.filter on the other hand is use to filter array based on condition. This will return a subset of original data but elements will be same. You cannot change element structure.
Array.reduce is a tool that address cases where you need to return selected elements with parsed value. You can achieve same by chaining .filter().map() but then its an overkill as it would result in O(2n).
Object.assign In JS objects are passed by reference. So if you assign an object to a variable, you are not copying entire object, but only reference. So it you change anything in this variable, it will also reflect in original object. To avoid this, you need to copy value. This is where Object.assign comes. Note, its not supported by old browsers. For them you can check following post - What is the most efficient way to deep clone an object in JavaScript?
Note: All array functions are part of functional programming paradigm and are used to make your code more readable and concise but they come at an expense of performance. Traditional for will always perform faster then them. So if you want to focus on performance, always try to use for (though difference is very small but can add up for multiple cases and become substantial)