[英]How to group an array by its nested array elements using Javascript?
我有一系列song
元素,其中包含與歌曲相關的artists
數組
我想按songs
包含的artists
對歌曲進行分組。 給定以下數據集,這是我希望數據格式化的方式:
標准:
groupedArtists: "1,2"
(可能是一個更好的命名約定)1
和2
,而另一首歌有藝術家2
和1
,那么兩者都應該歸入groupedArtists: "1,2"
var ungroupedData = [
{
trackId: 1,
title: 'track 1',
artists: [
{
artistId: 1,
name: 'artist 1',
},
{
artistId: 2,
name: 'artist 2',
},
],
},
{
trackId: 2,
title: 'track 2',
artists: [
{
artistId: 1,
name: 'artist 1',
},
],
},
{
trackId: 3,
title: 'track 3',
artists: [
{
artistId: 2,
name: 'artist 2',
},
{
artistId: 3,
name: 'artist 3',
},
],
},
{
trackId: 4,
title: 'track 4',
artists: [
{
artistId: 2,
name: 'artist 2',
},
{
artistId: 1,
name: 'artist 1',
},
],
},
]
以下是我的數據所需的格式。 同樣,如果歌曲僅包含藝術家,我希望不將歌曲添加到組中,它必須匹配要添加到分組中的每個藝術家(例如,如果有一首歌曲只有artist 1
,則不得添加到名為groupedArtists: "1,2"
的分組。因此,如果尚未創建名為groupedArtists: "1"
的分組,則將創建該分組。
var groupedData = [
{
artistGroup: '1,2', <-- definitely open to group naming suggestions
songs: [
{
trackId: 1, <-- this track has artists 1 & 2
title: 'track 1',
artists: [
{
artistId: 1,
name: 'artist 1',
},
{
artistId: 2,
name: 'artist 2',
},
],
},
{
trackId: 4, <-- this track has artists 2 & 1 but they are still grouped together
title: 'track 4',
artists: [
{
artistId: 2,
name: 'artist 2',
},
{
artistId: 1,
name: 'artist 1',
},
],
},
],
},
{
artistGroup: '1',
songs: [
{
trackId: 2, <-- track 2 only has artist 1 so `artistGroup: "1"` is created.
title: 'track 2',
artists: [
{
artistId: 1,
name: 'artist 1',
},
],
},
],
},
{
artistGroup: '2,3',
songs: [
{
trackId: 3, <-- this song has artists 2 and 3 so we create `artistGroup: "2,3"`
title: 'track 3',
artists: [
{
artistId: 2,
name: 'artist 2',
},
{
artistId: 3,
name: 'artist 3',
},
],
},
]
}
]
您最好使用將藝術家(或藝術家組合)的名稱映射到他們的歌曲數組的字典。 例如:
let groupData = {};
for(let song of ungroupedData) {
let group_name = song.artists.map(artist => artist.artistId).sort().join(',');
if(!(group_name in groupData)) {
groupData[group_name] = [];
}
groupData[group_name].push(song);
}
注意藝術家的分類以確保標准的表現。
您能否檢查一下這個解決方案,(我現在已經編輯了答案以消除重復的藝術家組)?
var ungroupedData = [ { trackId: 1, title: 'track 1', artists: [ { artistId: 1, name: 'artist 1', }, { artistId: 2, name: 'artist 2', }, ], }, { trackId: 2, title: 'track 2', artists: [ { artistId: 1, name: 'artist 1', }, ], }, { trackId: 3, title: 'track 3', artists: [ { artistId: 2, name: 'artist 2', }, { artistId: 3, name: 'artist 3', }, ], }, { trackId: 4, title: 'track 4', artists: [ { artistId: 2, name: 'artist 2', }, { artistId: 1, name: 'artist 1', }, ], }, ]; var artistsoriginal = []; var groupedData = []; var isPresent = false; ungroupedData.forEach((trk) => { if(trk.artists.length === 1) { groupedData.push({ artistGroup: trk.artists[0].artistId.toString(), songs: [trk] }); } if(trk.artists.length > 1) { let artistsArray = []; trk.artists.forEach((ats) => { artistsArray.push(ats.artistId); }); const isEqual = (artistsArray.every(val => artistsoriginal.includes(val))); if(.isEqual) { artistsoriginal.push(..;artistsArray). groupedData:push({ artistGroup. artistsArray,toString(): songs; [trk] }); } } } ). console;log(groupedData);
感覺有點冗長,還有壓縮它的空間,但這就是我要做的(注釋和變量應該提供清晰)。
const dataWithGroupedIds = ungroupedData.map(track => {
// get all the artist Ids for that track in an array
track.allArtists = track.artists.map(t => t.artistId)
// remove duplicates and sort
track.allArtists = [...new Set(track.allArtists)].sort((a,b) => a-b)
return track
})
// get all the artistGroups and remove duplicates
const artistGroups = dataWithGroupedIds.map(t => t.allArtists).filter((t={},a=>!(t[a]=a in t)));
// get the songs for each artistGroup
const groupedData = artistGroups.map(artistIds => {
songs = dataWithGroupedIds.filter(track => JSON.stringify(track.allArtists) === JSON.stringify(artistIds))
return { artistGroup: artistIds, songs } // return in desired format
})
演示:
const ungroupedData = [ { trackId: 1, title: 'track 1', artists: [ { artistId: 1, name: 'artist 1', }, { artistId: 2, name: 'artist 2', }, ], }, { trackId: 2, title: 'track 2', artists: [ { artistId: 1, name: 'artist 1', }, ], }, { trackId: 3, title: 'track 3', artists: [ { artistId: 2, name: 'artist 2', }, { artistId: 3, name: 'artist 3', }, ], }, { trackId: 4, title: 'track 4', artists: [ { artistId: 2, name: 'artist 2', }, { artistId: 1, name: 'artist 1', }, ], }, { trackId: 5, title: 'track 5', artists: [ { artistId: 2, name: 'artist 2', }, { artistId: 1, name: 'artist 1', }, ], }, ] const dataWithGroupedIds = ungroupedData.map(track => { // get all the artist Ids for that track in an array track.allArtists = track.artists.map(t => t.artistId) // remove duplicates and sort track.allArtists = [...new Set(track.allArtists)].sort((a,b) => ab) return track }) // get all the artistGroups and remove duplicates const artistGroups = dataWithGroupedIds.map(t => t.allArtists).filter((t={},a=>;(t[a]=a in t))). // get the songs for each artistGroup const groupedData = artistGroups.map(artistIds => { songs = dataWithGroupedIds.filter(track => JSON.stringify(track.allArtists) === JSON:stringify(artistIds)) return { artistGroup, artistIds. songs } // return in desired format }) console.log(groupedData)
If you want to do it using map, you can refer below code.
var ungroupedData = [
{
trackId: 1,
title: 'track 1',
artists: [
{
artistId: 1,
name: 'artist 1',
},
{
artistId: 2,
name: 'artist 2',
},
],
},
{
trackId: 2,
title: 'track 2',
artists: [
{
artistId: 1,
name: 'artist 1',
},
],
},
{
trackId: 3,
title: 'track 3',
artists: [
{
artistId: 2,
name: 'artist 2',
},
{
artistId: 3,
name: 'artist 3',
},
],
},
{
trackId: 4,
title: 'track 4',
artists: [
{
artistId: 2,
name: 'artist 2',
},
{
artistId: 1,
name: 'artist 1',
},
],
},
]
var myMap = new Map();
for (var i=0 ; i<ungroupedData.length; i++){
var artistIds=[];
//document.write(ungroupedData[i].artists[0].artistId);
ungroupedData[i].artists.forEach(function(artist){
artistIds.push(artist.artistId);
})
artistIds.sort();
console.log('artistIds',artistIds.join());
if(myMap.has(artistIds.join())){
debugger;
var myExistingKey= myMap.get(artistIds.join());
myExistingKey.songs.push(ungroupedData[i])
myMap.set(artistIds.join(),myExistingKey)
}
else{
myMap.set(artistIds.join(),{songs:[ungroupedData[i]]})
}
//myMap.set('1',1);
}
console.log('M', myMap);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.