2017-02-14 107 views
1

我想从给定的目录中选择一些随机文件。以下是我目前的实施;然而,文件夹内有太多的文件迭代它们,然后选择几个随机的文件似乎矫枉过正。如何使用Node.js从给定路径中选择多个随机文件?

有没有更好的解决方案?因为我在想知道文件夹内的所有文件是随机选择的前提条件?

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. 该文件夹包含超过预期
  3. 减档为尽快
的代码仍然工作

回答

1

基本上在下面的代码中,我创建了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 

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

1

首先,你不需要映射到concat你的目录路径,这将循环遍历整个文件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)) 
} 
+0

感谢这个解决方案更好地拥有像@treeless那样的'hashCheck'。 –

+1

@李新阳如果你了解Array.splice,它会根据索引取出项目。那么为什么你仍然需要使用hashCheck来检查重复文件?如果在此之后需要为其他目的重用变量文件,则可以使用Object.assign([],files)对其进行复制。 – Simon

2

好,readDir & readDirSync返回数组。您可以通过使用length属性来避免通过整个路径数组进行映射。我们可以使用一定百分比的长度制作一个动态样本集,然后将样本存储在一个新的数组中。

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]); 
} 
1

这是一个简单的实现。您还应该考虑使用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; });