2017-02-14 80 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; }); 
相關問題