首页 > 解决方案 > 尝试将二维数组下载为 .csv,但我正在为每一行返回一个文件

问题描述

这是我的代码:


function getRelease(idFiltered) {
  return fetch(`https://api.discogs.com/releases/${idFiltered}`, {
    'User-Agent': 'Dispodger/0.1',
  })
  .then(response => response.json())
  .then(data => {
    if (data.message === 'Release not found.') {
      return { error: `Release with ID ${idFiltered} does not exist` };
    } else {
      const id = data.id;
      const artists = data.artists ? data.artists.map(artist => artist.name) : [];
      const country = data.country || 'Unknown';
      const released = data.released_formatted || 'Unknown';
      const genres = data.genres || [];
      const styles = data.styles || [];
      const tracklist = data.tracklist ? data.tracklist.map(track => track.title) : [];

      console.log(idFiltered);
      console.log(artists, country, released, genres, styles, tracklist)

      const rows = [
        [idFiltered, artists, country, released, genres, styles, tracklist],

      ];

      const ROW_NAMES = ["Release ID", "artists", "country", "released", "genres", "styles", "tracklist"];

      console.log(rows);

      let csvContent = "data:text/csv;charset=utf-8,"
      + ROW_NAMES + "\n" + rows.map(e => e.join(",")).join("\n");

      console.log(csvContent);

      var encodedUri = encodeURI(csvContent);
      var link = document.createElement("a");
      link.setAttribute("href", encodedUri);
      link.setAttribute("download", "my_data.csv");
      document.body.appendChild(link); // Required for FF

      link.click();

    }
  });
}

它非常接近我想要的,但我每行输出返回一个文件,而不是将每一行附加到单个文件。从我所见,似乎有许多不同的方法可以将数据连接到 csv 文件中,例如使用for循环或forEach()方法,以及push()将每个项目推入新数组的方法。

我想我想做的事情的逻辑是......

在此先感谢您的任何指点。

编辑:输出应该是这样的:

   Release ID,artists,country,released,genres,styles,tracklist\n
   1,The Persuader,Sweden,Mar 1999,Electronic,Deep House,Östermalm,Vasastaden,Kungsholmen,Södermalm,Norrmalm,Gamla Stan\n
   2,Mr. James Barth & A.D.,Sweden,Jun 1998,Electronic,Broken Beat,Techno,Tech House,A Sea Apart,Dutchmaster,Inner City Lullaby,Yeah Kid!\n
   3,Josh Wink,US,13 Jul 1999,Electronic,Techno,Tech House,Untitled 8,Anjua (Sneaky 3),When The Funk Hits The Fan (Mood II Swing When The Dub Hits The Fan),What's The Time, Mr. Templar,Vol. 2,Political Prisoner,Pop Kulture,K-Mart Shopping (Hi-Fi Mix),Lovelee Dae (Eight Miles High Mix),Sweat,Silver,Untitled,Boom Box,Track 2\n
   4,Faze Action,US,02 Nov 1999,Electronic,House,Deep House,Moving Cities,To Love Is To Grow,Isis,Heartbeat,Samba,Got To Find A Way,Kariba,Space Disco,In The Trees,Turn The Point (U.S. Version),Mas,Horizons\n
   5,Datacide,Germany,15 Jan 1995,Electronic,Abstract,Ambient,Downtempo,Flashback Signal,Flowerhead,Deep Chair,So Much Light,Sixties Out Of Tune\n

现在,我说这样的话,因为这仍然不能解决每个逗号分隔值都将位于其自己的单元格中的问题,而我实际上希望将每个数据项的流派、样式和曲目列表组合起来成单个单元格,如下所示:

[发行 ID][艺术家][国家/地区][发行][流派 1,流派 2,...][风格 1,风格 2,...][轨道 1,轨道 2,...]

(其中 [] 是一个单元格)

但在我将输出放入单个文件之前,我真的没有准备好尝试解决这个问题。如果我试图一次解决两个问题,我几乎一定会陷入困境。

我正在访问的网站的文档位于https://www.discogs.com/developers

这就是我在控制台中登录的内容

标签: javascriptcsvexport-to-csv

解决方案


第一个问题——深层次的问题——是发布工件的形状是二维的,因此编译多个发布会产生三个维度。CSV 和电子表格仅包含两个维度。

该怎么办?如果需要简单的 CSV,一个想法是通过将数组属性转换为具有非逗号分隔符的字符串来展平数据。另一个想法是通过截断数组来丢失一些数据。(从语义上讲,音乐作品中通常有一个“主要艺术家”,也许我们只关心他们?看起来api在艺术家数组中返回了一个“角色”。也许这是一个关于谁是重要艺术家的线索?)

还有一种想法是多个 CSV 与“外键”相互引用,这可能会捕获所有维度,但这对于某些下游需求可能是错误的。

好的,这两个都是“扁平化的想法”

// this produces a single row of a releases table (demonstrating two ways to flatten):
// [ id, title, firstArtist, genre;genre;genre ]
//
function getOneRelease(idFiltered) {
  return fetch(`https://api.discogs.com/releases/${idFiltered}`, {
    'User-Agent': 'Dispodger/0.1',
  })
  .then(response => response.json())
  .then(data => {
    if (data.message === 'Release not found.') {
      return { error: `Release with ID ${idFiltered} does not exist` };
    } else {
      // flatten this data to be one dimensional by
      // truncating the array attributes to their first element
      const artist0 = data.artists.length ? data.artists[0] : ''
            
      // flatten using some delimeter, NOT A COMMA, to join the array attribute
      // into a singular string
      const allGenres = data.genres.join(';');  // note the semicolon won't upset a csv parse
      return [ data.id, data.title, artist0, allGenres ]
    }
  })
}

// this produces an array of arrays, each inner array is a release
function getReleases(arrayOfIds) {
  const promises = arrayOfIds.map(id => getOneRelease(id));
  return Promise.all(promises)
}

// get releases and add a header to produce csv data
getReleases([1,2,3]).then(results => {
  const data = [ ['id', 'title', 'mainArtist', 'genres'], ...results ];
  // csv is the inner arrays joined by commas and those joined by \n
  const csv = data.map(r => r.join(',')).join('\n');
})

推荐阅读