如何使用Node.js从给定的path中select一些随机文件?

我试图从给定的目录中select一些随机文件。 以下是我目前的实施情况。 然而,文件夹里面有太多的文件迭代它们,然后挑选几个随机的文件似乎矫枉过正。

有更好的解决scheme吗? 因为我在想的是知道文件夹内的所有文件是随机select的前提条件?

const dirs = fs.readdirSync(IMAGE_BANK_SRC) .map(file => { return path.join(IMAGE_BANK_SRC, file); }); const srcs_dup = []; dirs.forEach(path => { fs.readdirSync(path).forEach(file => { srcs_dup.push(file); }); }); // Pick few random ones from `srcs_dup` 

要求

  1. 所选的随机文件应该是唯一的
  2. 如果该文件夹包含的文件比预期的less,该代码仍在工作
  3. 尽可能快

基本上在下面的代码中,我创build了随机文件索引的randomIndex()。 获得文件列表后 我做了一个while循环,从目录列表中抓取一个随机文件并将其添加到数组中。

  //Grabs a random index between 0 and length function randomIndex(length) { return Math.floor(Math.random() * (length)); } //Read the directory and get the files const dirs = fs.readdirSync(IMAGE_BANK_SRC) .map(file => { return path.join(IMAGE_BANK_SRC, file); }); const srcs_dup = []; const hashCheck = {}; //used to check if the file was already added to srcs_dup var numberOfFiles = dirs.length / 10; //OR whatever # you want //While we haven't got the number of files we want. Loop. while (srcs_dup.length < numberOfFiles) { var fileIndex = randomIndex(dirs.length-1); //Check if the file was already added to the array if (hashCheck[fileIndex] == true) { continue; //Already have that file. Skip it } //Add the file to the array and object srcs_dup.push(dirs[fileIndex]); hashCheck[fileIndex] = true; } console.log(srcs_dup); //The list of your files 

如果这不起作用。 让我知道。

那么, readDirreadDirSync返回一个数组。 您可以通过使用length属性来避免通过整个path数组映射。 我们可以用一个百分比的长度做一个dynamic样本集,然后将样本存储在一个新的数组中。

 const dirs = fs.readdirSync(IMAGE_BANK_SRC); const length = dirs.length; const sampleSet = 25/100 * length; const getRandomIndex = length => Math.floor( Math.random() * length ); let samples = []; let usedIndices = []; let randomIndex = undefined; for (let i = 0; i < sampleSet; i++){ do { randomIndex = getRandomIndex( length ); } while ( usedIndices.includes( randomIndex ) ); usedIndicies.push( randomIndex ); samples.push( dirs[randomIndex] ); } 

这是一个简单的实现。 你也应该考虑使用path.resolve()方法。

 const dirs = fs.readdirSync(IMAGE_BANK_SRC) .map((e) => { return path.join(IMAGE_BANK_SRC, e); }); // New random list of dirs const randomList = dirs.slice(0) .map((e) => { return Math.random() < .5 ? e : null; }) .filter((e) => { return e != null; }); 

首先,您不需要映射到您的目录path,这将循环遍历整个文件1次。 其次,循环你需要的文件数量

 let result = [] let requiredCount = 3; let files = fs.readdirSync(IMAGE_BANK_SRC) while(requiredCount-- && files.length) { let length = files.length; let selectedIndex = Math.floor(Math.random() * length) let selected = files.splice(selectedIndex, 1); result.push(path.join(IMAGE_BANK_SRC, selected)) }