Javascript/nodejs динамически создает объект JS с вложенными массивами

У меня есть массив таких объектов Js:

const source = 
  [ { title: 'Expanse', season: 1, episode: 1, path: 'download.mkv' } 
  , { title: 'Expanse', season: 1, episode: 2, path: 'download.mkv' } 
  , { title: 'GoT',     season: 7, episode: 1, path: 'download.mkv' } 
  , { title: 'GoT',     season: 8, episode: 1, path: 'download.mkv' } 
  , { title: 'GoT',     season: 8, episode: 4, path: 'download.mkv' } 
  ] 

Я пытаюсь прочитать этот массив и создать один объект, в котором будут храниться все данные, например так: поэтому из каждого узла я могу легко получить все соответствующие данные. Я пытался сделать это в течение нескольких дней, но, похоже, не могу заставить его работать, ПОЖАЛУЙСТА, ПОМОГИТЕ NUBE! в начале я думал, что могу просто сделать

videos["Expanse"]["season"]["episode"]["path"] = "..."  

он создаст все ключи (вроде базы данных Firebase в реальном времени, но, видимо, это не так просто)

const videos = 
  [ { title: 'Expanse', seasons: 
      [ { season: 'season 1', episodes: 
          [ { name: 'episode 1', path: 'download.mkv' } 
          , { name: 'episode 2', path: 'download.mkv' } 
    ] } ] } 
  , { title: 'GoT', seasons: 
      [ { season: 'season 7', episodes: 
          [ { name: 'episode 1', path: 'download.mkv' } 
        ] } 
      , { season: 'season 8', episodes: 
          [ { name: 'episode 1', path: 'download.mkv' } 
          , { name: 'episode 4', path: 'download.mkv' } 
  ] } ] } ] 

🤔 А знаете ли вы, что...
JavaScript позволяет создавать мобильные приложения для iOS и Android с использованием фреймворков, таких как React Native и NativeScript.


1
183
2

Ответы:

Вы можете использовать уменьшить и создать промежуточные функции следующим образом:

function buildStructure(source) {
  return {
    videos: source.reduce((res, episode) => {
      let show = res.find(s => s.title === episode.title);
      if (!show) {
        show = { title: episode.title, seasons: [] };
        res.push(show);
      }
      addEpisodeToShow(show, episode);
      return res;
    }, [])
  };
}

function addEpisodeToShow(show, episode) {
  let season = show.seasons.find(s => s.season === `season ${episode.season}`);
  if (!season) {
    season = { season: `season ${episode.season}`, episodes: [] };
    show.seasons.push(season);
  }
  addEpisodeToSeason(season, episode);
  show.seasons.sort(compareFactory('season'));
}

function addEpisodeToSeason(season, episode) {
  season.episodes.push({
    name: `episode ${episode.episode}`,
    path: episode.path
  });
  season.episodes.sort(compareFactory('name'));
}

function compareFactory(key) {
  return function(a, b) {
    var _a = +(a[key].replace(/\D/g, '')),
        _b = +(b[key].replace(/\D/g, ''));
    return _a - _b;
  }
}

const source = [
  {"title": "Expanse", "season": 1, "episode": 1, "path": "download.mkv" },
  {"title": "GoT", "season": 8, "episode": 4, "path": "download.mkv" },
  {"title": "Expanse", "season": 1, "episode": 2, "path": "download.mkv" },
  {"title": "GoT", "season": 7, "episode": 1, "path": "download.mkv" },
  {"title": "GoT", "season": 8, "episode": 1, "path": "download.mkv" }
];
console.info( buildStructure(source) );
.as-console-wrapper { max-height: 100% !important; }

Решено

"просто" так...

const source = 
  [ { title: 'Expanse', season: 1, episode: 1, path: 'download.mkv'} 
  , { title: 'Expanse', season: 1, episode: 2, path: 'download.mkv'} 
  , { title: 'GoT', season: 7, episode: 1, path: 'download.mkv'} 
  , { title: 'GoT', season: 8, episode: 1, path: 'download.mkv'} 
  , { title: 'GoT', season: 8, episode: 4, path: 'download.mkv'} 
  ]
  
const result = source.reduce((a,{title,season,episode,...more} )=>
  {
  let titleX = a.find(x=>x.title===title)
  if (!titleX)
    {
    titleX = { title, seasons:[] }
    a.push(titleX)
    }
  let seasonX = titleX.seasons.find(x=>x.season===`season ${season}`)
  if (!seasonX)
    {
    seasonX = { season:`season ${season}`, episodes:[] }
    titleX.seasons.push(seasonX)
    }
  seasonX.episodes.push({ name:`episode ${episode}`, ...more })
  return a  
  },[])

  
console.info(  result )
.as-console-wrapper { max-height: 100% !important; top: 0; }