how to remove Duplicate from list array [duplicate] - javascript

This question already has answers here:
How to remove all duplicates from an array of objects?
(77 answers)
Closed 7 years ago.
var cars = [
{ year: 2007, model: "Ford F-150" },
{ year: 2011, model: "Toyota Camry" },
{ year: 2007, model: "Ford F-150" },
{ year: 2007, model: "Ford F-150" },
{ year: 2005, model: "Dodge RAM" }
{ year: 2005, model: "Dodge RAM" };
];
How Remove duplicate from this array list

It is easy to filter duplicates base on indexOf condition, this works for simple items. In your case you can't use it because two similar objects in array are not identical so indexOf will not help.
For this situation it is convenient to make use of Array.prototype.reduce:
var cars = [
{ year: 2007, model: "Ford F-150" },
{ year: 2011, model: "Toyota Camry" },
{ year: 2007, model: "Ford F-150" },
{ year: 2007, model: "Ford F-150" },
{ year: 2005, model: "Dodge RAM" },
{ year: 2005, model: "Dodge RAM" }
];
cars = cars.reduce(function(prev, curr) {
var inArray = prev.some(function(car) {
return car.model === curr.model && car.year === curr.year;
});
if (!inArray) {
prev.push(curr);
}
return prev;
}, []);
alert(JSON.stringify( cars, null, 4) )

Related

How can I remove comma between first and last names in array?

I have to remove the comma between the first and last names of "name" in an array called "players" using .map() and .split().
This is the array I'm given:
const players = [
{ name: 'Modrić, Luka', year: 1985 },
{ name: 'Christian, Eriksen', year: 1992 },
{ name: 'Griezmann, Antoine', year: 1991 },
{ name: 'Achraf, Hakimi', year: 1998 },
{ name: 'Martínez, Lautaro', year: 1997 }
];
This is the code I have so far, to get name out of the array using .map():
const mapped = players.map(({ name }) => {
return name;
})
console.log(mapped);
Which logs this in the console:
[
'Modrić, Luka',
'Christian, Eriksen',
'Griezmann, Antoine',
'Achraf, Hakimi',
'Martínez, Lautaro'
]
Now how do I use .split() to remove the the commas between the first and last name? Im lost :(
Thanks for any help! :)
I tried using .map to get each name from the players array. Then I tried using .split() to no avail :(
You can use String#replace.
const players = [
{ name: 'Modrić, Luka', year: 1985 },
{ name: 'Christian, Eriksen', year: 1992 },
{ name: 'Griezmann, Antoine', year: 1991 },
{ name: 'Achraf, Hakimi', year: 1998 },
{ name: 'Martínez, Lautaro', year: 1997 }
];
let res = players.map(({name}) => name.replace(',', ''));
console.log(res);
const players = [
{ name: 'Modrić, Luka', year: 1985 },
{ name: 'Christian, Eriksen', year: 1992 },
{ name: 'Griezmann, Antoine', year: 1991 },
{ name: 'Achraf, Hakimi', year: 1998 },
{ name: 'Martínez, Lautaro', year: 1997 }
];
// use `split` to split
console.log(players.map(player => player.name.split(', ')))
If you really have to use split, which then you would have to use join to change it back to a string:
{ name: 'Modrić, Luka', year: 1985 },
{ name: 'Christian, Eriksen', year: 1992 },
{ name: 'Griezmann, Antoine', year: 1991 },
{ name: 'Achraf, Hakimi', year: 1998 },
{ name: 'Martínez, Lautaro', year: 1997 }
];
const mapped = players.map(({ name }) => {
let splitName = name.split(',');
return splitName.join('')
})
console.log(mapped);
But I think this would be better:
{ name: 'Modrić, Luka', year: 1985 },
{ name: 'Christian, Eriksen', year: 1992 },
{ name: 'Griezmann, Antoine', year: 1991 },
{ name: 'Achraf, Hakimi', year: 1998 },
{ name: 'Martínez, Lautaro', year: 1997 }
];
const mapped = players.map(({ name }) => {
return name.replace(',', '')
})
console.log(mapped);

Create sub array with key value and sort it

Given below is an array of objects, need to create sub-array in it with common make key, also all sub-array and main array needs to be sorted as follows:
the main array to be sorted on make key alphabetically.
sub-arrays to be sorted ASC on the basis of the year.
Input Array:
const cars = [
{
"make": "audi",
"model": "r8",
"year": "2006"
}, {
"make": "audi",
"model": "s5",
"year": "2005"
}, {
"make": "ford",
"model": "mustang",
"year": "2012"
}, {
"make": "ford",
"model": "fusion",
"year": "2015"
}, {
"make": "kia",
"model": "optima",
"year": "2012"
},
];
Desired Array:
const cars = [
{
"make": "audi",
"list": [
{
"model": "s5",
"year": "2005",
},
{
"model": "r8",
"year": "2006",
},
],
},
{
"make": "ford",
"list": [
{
"model": "mustang",
"year": "2012",
},
{
"model": "fusion",
"year": "2015",
},
],
},
{
"make": "kia",
"list": [
{
"model": "optima",
"year": "2012",
},
],
},
];
What I have tried yet:
let filteredData = [];
cars.forEach((value)=>{
var foundIndex = filteredData.findIndex( car => car.make === value.make );
if(foundIndex != -1){
let carData = filteredData[foundIndex];
const {list} = carData;
let nextObj = {'model': value.model, 'year': value.year};
const newData = [...list, nextObj];
carData['list'] = newData;
filteredData[foundIndex] = carData;
}else{
let values = {'model': value.model, 'year': value.year};
let data = [values];
let obj = {'make':value.make, 'list': data};
filteredData.push(obj);
}
});
const sortedCars = filteredData.sort((a, b) => a.make.localeCompare(b.make));
Any optimal solution for this to make it better is welcomed.
This is really just a 'group by' with sorting. To avoid having to sort multiple nested arrays in the result you can sort (a copy) of the array by year before grouping, and then sort the result by make afterwards. Here using a for...of loop grouping into an object and then sorting the Object.values() as the result.
const cars = [
{ make: 'ford', model: 'fusion', year: '2015' },
{ make: 'audi', model: 'r8', year: '2006' },
{ make: 'audi', model: 's5', year: '2005' },
{ make: 'ford', model: 'mustang', year: '2012' },
{ make: 'kia', model: 'optima', year: '2012' },
];
const grouped = {};
for (const { make, ...rest } of [...cars].sort((a, b) => a.year - b.year)) {
(grouped[make] ??= { make, list: [] }).list.push({ ...rest });
}
const result = Object.values(grouped).sort((a, b) =>
a.make.localeCompare(b.make)
);
console.log(result);
Alternatively, because javascript objects sort integer properties by default you can 'group by' year within each list and then map the resulting object values to arrays. The outer array will need to be sorted explicitly.
const cars = [
{ make: 'ford', model: 'fusion', year: '2015' },
{ make: 'audi', model: 'r8', year: '2006' },
{ make: 'audi', model: 's5', year: '2005' },
{ make: 'ford', model: 'mustang', year: '2012' },
{ make: 'kia', model: 'optima', year: '2012' },
];
const result = Object.values(
cars.reduce((a, { make, year, ...rest }) => {
a[make] ??= { make, list: {} };
a[make].list[year] ??= [];
a[make].list[year].push({ year, ...rest });
return a;
}, {}))
.map(({ make, list }) => ({ make, list: Object.values(list).flat() }))
.sort((a, b) => a.make.localeCompare(b.make));
console.log(result);
let filteredData = [];
cars.forEach((value)=>{
var foundIndex = filteredData.findIndex( car => car.make === value.make );
if(foundIndex != -1){
let carData = filteredData[foundIndex];
const {list} = carData;
let nextObj = {'model': value.model, 'year': value.year};
let newData = [...list, nextObj];
newData.sort((a, b) => a.year.localeCompare(b.year));
carData['list'] = newData;
filteredData[foundIndex] = carData;
}else{
let values = {'model': value.model, 'year': value.year};
let data = [values];
let obj = {'make':value.make, 'list': data};
filteredData.push(obj);
}
});
const sortedCars = filteredData.sort((a, b) => a.make.localeCompare(b.make));

Group array by year and month

I would like to group an array with events by year and month. My data looks like this:
const events = [
{
name: "event 1",
year: 2021,
month: 1,
},
{
name: "event 2",
year: 2021,
month: 9,
},
{
name: "event 3",
year: 2021,
month: 1,
},
{
name: "event 4",
year: 2022,
month: 7,
},
]
And my expected outcome should be something like this:
[
{
year: 2021,
month: 1,
events: [
{
name: "event 1"
},
{
name: "event 3"
}
]
},
{
year: 2021,
month: 9,
events: [
{
name: "event 2"
}
]
}
]
What would be the best approach to do this? I found a couple stackoverflow posts to group an array by it's key value but that not what I'm looking for.
const groupBy = (array, key) => {
return array.reduce((result, currentValue) => {
// If an array already present for key, push it to the array. Else create an array and push the object
(result[currentValue[key]] = result[currentValue[key]] || []).push(currentValue);
// Return the current iteration `result` value, this will be taken as next iteration `result` value and accumulate
return result;
}, {}); // empty object is the initial value for result object
};
const groupedByYear = groupBy(events, 'year');
You can do this with reduce and Object.values
const events = [
{
name: "event 1",
year: 2021,
month: 1,
},
{
name: "event 2",
year: 2021,
month: 9,
},
{
name: "event 3",
year: 2021,
month: 1,
},
];
const result = Object.values(events.reduce( (acc,evt) => {
const key = `${evt.year}-${evt.month}`;
if(!acc[key]) {
acc[key] = {year: evt.year, month: evt.month, events:[]}
}
acc[key].events.push( {name:evt.name} );
return acc;
},{}));
console.log(result);
You could take a dynamic approach by using a combined key for wanted properties for grouping.
Then remove all keys of grouing and push a new object without unwanted properties.
const
events = [{ name: "event 1", year: 2021, month: 1 }, { name: "event 2", year: 2021, month: 9 }, { name: "event 3", year: 2021, month: 1 }],
keys = ['year', 'month'],
result = Object.values(events.reduce((r, o) => {
let value,
key = keys.map(k => o[k]).join('|');
if (!r[key]) r[key] = { ...Object.fromEntries(keys.map(k => [k, o[k]])), events: [] };
r[key].events.push(keys.reduce((t, k) => (({ [k]: value, ...t } = t), t), o));
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

I want to turn a javascript array to create a new array

I want to display a graph of the total count for groupA and groupB for each month.
The graph library uses chart.js
I want to put the sum of the counts for each month in data:[].
I want to turn the array of values to be retrieved from the data to determine groupA and groupB, and put the count for each month into data
script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"
javascript:
var users = #{raw #user_counts.to_json}
console.log(users)
var ct = document.getElementById('ex_chart');
var ex_chart = new Chart(ct, {
type: 'horizontalBar',
data: {
labels: ["Jan", "Feb", "Mar", "Apr", "May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
datasets: [
{
label: 'groupA',
data: [],
backgroundColor: '#C7CED7'
},
{
label: 'groupB',
data: [],
backgroundColor: '#0068B4'
}
]
},
options: options
})
Contents of users
[
{
activity_type: "groupA"
count: 10
created_at: "2021-01-14T13:46:18.000Z"
id: 1
year: 2020
month: "Jan"
updated_at: "2021-01-14T13:46:18.000Z"
},
{
activity_type: "groupA"
count: 8
created_at: "2021-01-14T13:46:18.000Z"
id: 2
year: 2020
month: "Feb"
updated_at: "2021-01-14T13:46:18.000Z"
},
{
activity_type: "groupB"
count: 8
created_at: "2021-01-14T13:46:18.000Z"
id: 3
year: 2020
month: "Feb"
updated_at: "2021-01-14T13:46:18.000Z"
}
]
In technical terms, you want to group your user counts by two parameters: 'activityType' and 'month'.
Below is a solution using functional programming. You may modify keys, for example to add 'year' parameter, which actually makes sense.
const users = [
{
activity_type: "groupA",
count: 10,
year: 2020,
month: 1
},
{
activity_type: "groupA",
count: 17,
year: 2019,
month: 2,
},
{
activity_type: "groupA",
count: 8,
year: 2020,
month: 2,
},
{
activity_type: "groupB",
count: 8,
year: 2020,
month: 1,
}
];
const keys = ['activity_type', 'month'];
function matches(table, entry, keys) { // finds item with same values
return table.find(e => keys.every(k => e[k] == entry[k]));
}
const usersGroupedByKeys = users.reduce((cur, val) => {
let alreadyIn = matches(cur, val, keys);
if (alreadyIn) {
alreadyIn['count'] = alreadyIn['count'] + val['count'];
} else {
cur.push(val);
}
return cur;
}, []);
console.log(usersGroupedByKeys);
Check the Docs.

Filter through array of objects in javascript

I have a data structure that looks like this:
const carsData = [
{
name: "Cars",
collection: [
{ year: 2011, model: "B", price: 4400 },
{ year: 2015, model: "A", price: 32000 },
{ year: 2016, model: "B", price: 15500 }
]
},
{
name: "Trucks",
collection: [
{ year: 2014, model: "D", price: 18000 },
{ year: 2013, model: "E", price: 5200 }
]
},
{
name: "Convertibles",
collection: [
{ year: 2009, model: "F", price: 20000 },
{ year: 2010, model: "G", price: 8000 },
{ year: 2012, model: "H", price: 12500 },
{ year: 2017, model: "M", price: 80000 }
]
}
];
and want to return a new array let's say const newCarsData(see below) where collection consists of only objects with year higher than 2013, so it will look like this:
const newCarsData = [
{
name: "Cars",
collection:[
{ year: 2015, model: "A", price: 32000 },
{ year: 2016, model: "B", price: 15500 }
]
},
{
name: "Trucks",
collection: [
{ year: 2014, model: "D", price: 18000 }
]
},
{
name: "Convertibles",
collection: [
{ year: 2017, model: "M", price: 80000 }
]
}
];
I tried filter method collection.filter(x => x.year > 2013) inside of for loop, but couldn't make it work. At the end my code looked like this
const newCarsData = getNewData(carsData);
let arr = [];
function getNewData(somedata) {
for (let i = 0; i < somedata.length; i++) {
// console.log(somedata[i].collection);
for (let j = 0; j < somedata[i].collection.length; j++) {
let arr.push(somedata[i].collection[j]);
// console.log(somedata[i].collection[j]);
}
// return somedata[i].collection.filter(x => x.year > 2013);
}
return arr.filter(x => x.year > 2013);
}
Since the collection is in another array inside the array items, you can't directly use filter. You can use map first then use filter.
const carsData=[{name:"Cars",collection:[{year:2011,model:"B",price:4400},{year:2015,model:"A",price:32000},{year:2016,model:"B",price:15500}]},{name:"Trucks",collection:[{year:2014,model:"D",price:18000},{year:2013,model:"E",price:5200}]},{name:"Convertibles",collection:[{year:2009,model:"F",price:20000},{year:2010,model:"G",price:8000},{year:2012,model:"H",price:12500},{year:2017,model:"M",price:80000}]}]
const filteredCarData = carsData.map(carType => {
return {
...carType,
collection: carType.collection.filter(car => car.year>2013)
}
})
console.log(JSON.stringify(filteredCarData))
The ...carType notation collects the object properties in the new mapped object. If you have no other properties than name, you can instead do
const filteredCarData = carsData.map(carType => {
return {
name: carType.name,
collection: carType.collection.filter(car => car.year>2013)
}
})
You'll have to update your collection:
carsData.forEach(function(carData){
carData.collection = carData.collection.filter(x => x.year > 2013);
});
One way to do it can be using reduce.
var res = carsData.reduce((acc, value) => {
let data = { name: value.name, collections: value.collection.filter(v => v.year > 2013 )}
return acc.concat(data)
}, [])
You can actually, replace the reduce with a map:
carsData.map(value => {
return { name: value.name, collections: value.collection.filter(v => v.year > 2013 )}
})

Categories

Resources