簡體   English   中英

如何使用 Javascript 按嵌套數組元素對數組進行分組?

[英]How to group an array by its nested array elements using Javascript?

我有一系列song元素,其中包含與歌曲相關的artists數組

我想按songs包含的artists對歌曲進行分組。 給定以下數據集,這是我希望數據格式化的方式:

標准:

  • 一首歌應該只是一個組的一部分,所以如果一首歌有多個藝術家,它應該存儲在一個名為groupedArtists: "1,2" (可能是一個更好的命名約定)
  • 藝術家的排列順序無關緊要。如果一首歌有藝術家12 ,而另一首歌有藝術家21 ,那么兩者都應該歸入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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM