group by Date in Javascript - javascript

I have an array of birthdays
const birthdays = [
{name: 'John', birthday: '08-08-1960'},
{name: 'James', birthday: '08-25-1960'},
{name: 'Mary', birthday: '01-01-1990'},
]
and I need to generate a new array with the birthdays grouped by month-year
const grouped = [
{'08-1960': [
{name: 'John', birthday: '08-08-1960'},
{name: 'James', birthday: '08-25-1960'},
]},
{'01-1990': [
{name: 'Mary', birthday: '01-01-1990'},
]},
]
I was looking at something like this. using moment and lodash
let groupedResults = _.groupBy(results, (result) => moment(result['Date'], 'DD/MM/YYYY').startOf('isoWeek'));
but I canĀ“t imagine how to generate the new array structure (with the month-year as keys) thank you.
update: it should return an array not an object :facepalm

You can use reduce()
Apply reduce() on array of object and set accumulator to empty object {}
Then split() birthday by - and get only get first and third element.
If the key exist is accumulator that concat() new value to it. Otherwise concat() it to empty array [] and then set it as property of accumulator.
const arr = [
{name: 'John', birthday: '08-08-1960'},
{name: 'James', birthday: '08-25-1960'},
{name: 'John', birthday: '01-01-1990'},
]
let res = arr.reduce((ac,a) => {
let key = a.birthday.split('-');
key = `${key[0]}-${key[2]}`;
ac[key] = (ac[key] || []).concat(a);
return ac;
},{})
res = Object.entries(res).map(([k,v]) => ({[k]:v}))
console.log(res)

As explained here https://www.dyn-web.com/javascript/arrays/associative.php you can create arrays where the indexes are strings, but i won't work as a normal array.
Here is a snippet for doing what you want.
const birthdays = [
{name: 'John', birthday: '08-08-1960'},
{name: 'James', birthday: '08-25-1960'},
{name: 'Mary', birthday: '01-01-1990'},
];
const grouped = birthdays.reduce((prev, cur) => {
const date = new Date(cur.birthday);
const key = `${(date.getMonth() + 1)}-${date.getFullYear()}`;
if(!prev[key]){
prev[key] = [ cur ];
}
else{
prev[key].push(cur);
}
return prev;
}, []);
for(let i in grouped){
console.log(grouped[i]);
}

Related

How to remove object if object matches [duplicate]

This question already has answers here:
Object comparison in JavaScript [duplicate]
(10 answers)
Closed 1 year ago.
I am trying to remove object if object matches, I dont want to compare any object key, I just want to compare whole object with array of object, and if it matches, then I have to remove that object from original array.
let originalArray = [
{name: 'abc', country: 'eng'},
{name: 'xyz', country: 'ind'},
{name: 'pqr', country: 'us'}
]
let objectToBeRemove = [
{name: 'pqr', country: 'us'}
]
console.log(originalArray);
Expected output:
[
{name: 'abc', country: 'eng'},
{name: 'xyz', country: 'ind'}
]
I am not able to figure out how can I compare object, I can do it by id or any key, but I am making generic thing, so may be in few cases ID is not present, that's why I want to compare object
One way is to use Array#filter with Array#some + JSON.stringify() for comparison.
Note that Array#filter returns a new array. So the variable needs to be reassigned.
let originalArray = [
{name: 'abc', country: 'eng'},
{name: 'xyz', country: 'ind'},
{name: 'pqr', country: 'us'}
];
let objectToBeRemove = [
{name: 'pqr', country: 'us'}
];
originalArray = originalArray.filter(obj =>
objectToBeRemove.some(objToRemove =>
JSON.stringify(objToRemove) !== JSON.stringify(obj)
)
);
console.log(originalArray);
Note: Using JSON.stringify() is a little primitive for object comparison in my opinion. For instance the check would fail if the properties are in different order {country: 'us', name: 'pqr'}. Better way would be to do a deep comparison. For eg. using _.isEqual from loadash library. See here for more info.
Using loadash
let originalArray = [
{name: 'abc', country: 'eng'},
{name: 'xyz', country: 'ind'},
{name: 'pqr', country: 'us'}
];
let objectToBeRemove = [
{country: 'us', name: 'pqr'}
];
originalArray = originalArray.filter(obj =>
objectToBeRemove.some(objToRemove =>
!_.isEqual(objToRemove, obj)
)
);
console.log(originalArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
You can use "filter" function to do that: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
var myArr = [{name: "toto"}, {name: "tata"}, {name: "tutu"}];
var toRemove = {name: "tata"};
let ret = myArr.filter(function(el) {
return el.name != toRemove.name;
});
Or for removing multiple items:
var myArr = [{name: "toto"}, {name: "tata"}, {name: "tutu"}];
var toRemove = [{name: "tata"}, {name: "tutu"}];
for (var i = 0; i < toRemove.length; i++) {
let index = myArr.findIndex((el) => { // Search item index to remove
return el.name == toRemove[i].name;
});
if (index != -1) myArr.splice(index, 1); // Remove item in found index
}
To compare the equality of the complete object you could use the JSON.stringify() method.
Example;
JSON.stringfy(originalArray[i]) === JSON.stringfy(objectToBeRemove)
try this
let originalArray = [
{ name: 'abc', country: 'eng' },
{ name: 'xyz', country: 'ind' },
{ name: 'pqr', country: 'us' }
];
let objectToBeRemove = [
{ name: 'pqr', country: 'us' }
];
var finalResult = originalArray.filter(function(objFromA) {
return !objectToBeRemove.find(function(objFromB) {
return objFromA.name === objFromB.name
})
});
console.log('???',finalResult);

How to nest element of an object inside the same object in javascript?

I created a form to get some info from User, and I want to move some of their info into a nested object. the reason why is to better organize my data later in front-end.
As a simple example, how to create the following "newInfo" out of "oldInfo" in JavaScript?
oldInfo = {
name: 'John',
Age: '32',
friend1: 'Michael',
friend2: 'Peter',
};
newInfo = {
name: 'John',
Age: '32',
friends: {
friend1: 'Michael',
friend2: 'peter',
},
};
I'm sure this must be a repeated and simple topic, but I couldn't find any as I didn't know what keyword to search for.
You could explicitly assign it
const oldInfo = {
name: "John",
Age: "32",
friend1: "Michael",
friend2: "Peter",
}
const newInfo = {
name: oldInfo.name,
Age: oldInfo.Age,
friends: {
friend1: oldInfo.friend1,
friend2: oldInfo.friend2,
},
}
console.log(newInfo)
You can do this easily with spread operator:
const { name, Age, ...friends } = oldInfo;
newInfo = { name, Age, friends };
It simply extracts all fields except name and age as friends.
Example:
const oldInfo = {
name: 'John',
Age: '32',
friend1: 'Michael',
friend2: 'Peter',
};
const { name, Age, ...friends } = oldInfo;
const newInfo = { name, Age, friends };
console.log(newInfo);
If you have a dynamic number of friend: name key-value pairs and other properties that shouldn't be nested into friends then you can use Object.entries and reduce:
const oldInfo = {
name: 'John',
Age: '32',
friend1: 'Michael',
friend2: 'Peter',
};
const newInfo = Object.entries(oldInfo).reduce((acc, [k, v]) => {
if(k.startsWith('friend')) {
acc.friends ? acc.friends[k] = v : acc.friends = {[k]: v};
} else {
acc[k] = v;
}
return acc;
},{});
console.log(newInfo);

How can we transform a nested array inside an object into one concatenated string value separated by commas?

I have the following sample array:
mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
I need to transform it into something like:
mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: 'Lebanon, USA'},
{id: 15475, name: 'Emily', gender: 'Female', addresses: 'UK, France }
];
In this case, I added all nested arrays inside a an element of the mainArray into one single string value.
What I've done so far is, I extracted the key names of the mainArray:
extractedIndexes = ['id', 'name', 'gender', 'addresses'];
And made a loop to check the type of each element inside of the mainArray, and if it's an object I will concat the values of the nested array into one single string:
for (const idx of this.extractedIndexes) {
console.log(idx)
this.mainArray.forEach((elem) => {
let newItem = '';
if (typeof (elem[idx]) == 'object') {
elem[idx] = Object.keys(elem[idx]).forEach((key) => {
console.log(elem[idx][key])
// Add it to the field
})
console.log(elem[idx])
}
})
}
console.log(this.mainArray)
This line console.log(elem[idx][key]) is always returning the following:
{address1: "Lebanon"}
{address2: "USA"}
{address1: "UK"}
{address2: "France"}
Take note that here address1 and address2 are simple examples, as my real data contain multiple nested arrays, and each one have different new key names.
I tried to do the following:
if (typeof (elem[idx]) == 'object') {
elem[idx] = elem[idx].toString().split(',')
// Add it to the field
console.log(elem[idx])
}
But it returned [Object, Object].
So how can I transform a nested array into single concatenated string value?
Here is a stackblitz.
Just use map and use Object.values to get values from object:
mainArray.map(({addresses, ...rest}) => ({...rest, addresses:
addresses.map(s => Object.values(s)).join(', ')}) );
An example:
let mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
const result = mainArray.map(({addresses, ...rest}) => ({...rest, addresses: addresses.map(s => Object.values(s)).join(', ')}) );
console.log(result);
If you don't know whether the key is array, then you can try to use reduce method:
const result = mainArray.reduce((a, c)=> {
for (const key in c) {
if (Array.isArray(c[key]))
c[key] = c[key].map(s => Object.values(s)).join(', ');
}
a.push(c);
return a;
},[])
console.log(result);
An example:
let mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
const result = mainArray.reduce((a, c)=> {
for (const key in c) {
if (Array.isArray(c[key]))
c[key] = c[key].map(s => Object.values(s)).join(', ');
}
a.push(c);
return a;
},[])
console.log(result);
You could use recursive function to get addresses that will work on any nested structure and get the value if the key starts with address and value is not an object.
const data =[{"id":15475,"name":"Ali","gender":"Male","addresses":[{"address1":"Lebanon"},{"address2":"USA"}]},{"id":15475,"name":"Emily","gender":"Female","addresses":[{"address1":"UK"},{"address2":"France"}]}]
const flat = (data, prev = '') => {
let sep = prev ? ', ' : ''
let result = '';
for (let i in data) {
if (typeof data[i] == 'object') {
result += flat(data[i], prev + result)
} else if (i.startsWith('address')) {
result += sep + data[i]
}
}
return result
}
const result = data.map(({
addresses,
...rest
}) =>
({ ...rest,
addresses: flat(addresses)
}))
console.log(result)
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];<br>
function toString(arro) {
return arro.reduce(
(acc, rec) => {
return [...acc, Object.values(rec)]
}, []
).join(',')
}
const res = mainArray.map(
it => {
return Object.keys(it).reduce(
(acc, item) => {
if (typeof it[item] === 'object') {
return {...acc, [item]: toString(it[item])}
}
return {...acc, [item]: it[item]}
}, {}
)
}
)```

How can I convert an array of objects into an array of objects with the same values but with modified keys?

I have an array with objects and want to convert this to an array containing the same values but with different key names. (JavaScript)
For example, an array of
[{name: "Bob", age: 50, person: true}, {name: "Jerry", age: 20, person: true}]
becomes
[{identification: "Bob", years: 50, person: true}, {identification: "Jerry", years: 20, person: true}]
Using the Map function works perfectly here.
const people = [
{name: "Bob", age: 50, person: true},
{name: "Jerry", age: 20, person: true}
];
const formatted = people.map((person) => ({
identification: person.name,
years: person.age,
person: person.person
});
This should work for this problem.
I think that you may use the map method this method returns and array with the same length as the one you are mapping:
const array = [{name: "Bob", age: 50, person: true}, {name: "Jerry", age: 20, person: true}];
let newKeysArray = array.map( a => {
let obj = {
identification: person.name,
years: person.age,
person: person.person
};
return obj
} );
So inside the map you are assigning the values that you need to a new object and return the object as the mapped item.
Just in case you prefer to modify the objects in place, you can make use of a strategy by nverba here:
let rows = [
{name: "Bob", age: 50, person: true},
{name: "Jerry", age: 20, person: true}
];
let keyMaps = [
['name', 'identification'],
['age', 'years'],
];
for(let keyMap of keyMaps)
for(let row of rows)
delete Object.assign(row, {[keyMap[1]]: row[keyMap[0]] })[keyMap[0]];
console.log(rows);
keyMap[1] is the new key. keyMap[0] is the old key. Object.assign takes the value of the old key and places it in the new key. The delete keyword is confusing, but it doesn't apply to row as a whole. It's only deleting the old key.

Array Destructuring + spread syntax with specific field only?

let arr = [{name: 'john', age:17}, {name: 'Doe', age: 21}];
//let dropDownHumanOptions = ['All', ...arr.name, 'Cancel']
//let dropDownHumanOptions = ['All', ...{arr.name}, 'Cancel']
//Expected: let dropDownHumanOptions = ['All', 'john', 'Doe', 'Cancel']
I'm wondering if there is any similar syntax where we can just extracting one of the field and combine in the middle of another array by using spread syntax?
You need to spread the mapped names.
var array = [{name: 'john', age:17}, {name: 'Doe', age: 21}],
dropDownHumanOptions = ['All', ...array.map(({ name }) => name), 'Cancel'];
console.log(dropDownHumanOptions);

Categories

Resources