问题
I have an array of Js objects like this:
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' }
]
I'm trying to read this array and create one object the will hold all the data, like this: so from each node, i can easily retrieve all the relevant data.
I've been trying to do this for a few days, but cant seem to get it to work, PLEASE HELP a NUBE! at the beging I thought I could just do
videos["Expanse"]["season"]["episode"]["path"] = "..."
it will create all the keys (kind of like firebase realtime database but apparently it not as easy)
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' }
] } ] } ]
回答1:
"simply" this way...
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.log( result )
.as-console-wrapper { max-height: 100% !important; top: 0; }
回答2:
You could use reduce and create intermediary functions along these lines:
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.log( buildStructure(source) );
.as-console-wrapper { max-height: 100% !important; }
来源:https://stackoverflow.com/questions/65401527/javascript-nodejs-dynamically-build-js-object-with-nested-arrays