2016-01-12 4 views
2

У меня есть папка, которая содержит файлы:Получить упорядоченный список файлов с помощью Javascript

s1, s2, s3, ... s9, s10, s11, ... s99, s100, s101, s102, s103, ..., 

и скрипт, который выводит список этих файлов:

filesystem = require('fs'); 
filesystem.readdirSync('./folder').forEach(function (file) { 
    console.log(file); 
}); 

, но я получаю неупорядоченный список, как это:

s0, s1, s10, s100, s101, s102, s103, ... s11, s110, s111, s112, s12 

Я знаю причину, но я хочу, чтобы получить «номер» упорядоченный список, как это:

s1, s2, s3, ... s9, s10, s11, ... s99, s100, s101, s102, s103, ..., 
+0

имена папок не являются номерами и не могут быть оценены по номерам, поэтому они упорядочены по алфавиту. Однако, если у вас есть определенный шаблон для именования, из которого вы можете надежно извлечь номер, вы можете создать функцию, которая преобразует из строки в целое, и упорядочить список с помощью пользовательского сопоставления. – AlexanderMP

+0

Сначала используйте Async, если это возможно ... если readdirSync абсолютно необходимо. Во-вторых, он возвращает отсортированные имена файлов, просто они сортируются на основе строки. Если вам нужно отсортировать их по номерам, вам придется анализировать значения целых чисел из их имен, а затем применять сортировку. – Aukhan

+0

Повторяю, но короче: У вас есть определенный шаблон для имени файла? Это просто 's ##' для каждого файла, с которым вы будете работать? – AlexanderMP

ответ

1
filesystem.readdir('./folder', function(err, files) { 
    files.sort(function(file1, file2) { 
     var file1Int = parseInt(file1.replace(/^\D+/g, '')), 
      file2Int = parseInt(file2.replace(/^\D+/g, '')); 

     if (file1Int < file2Int) { 
      return -1; 
     } 
     if (file1Int > file2Int) { 
      return 1; 
     } 
     return 0; 

    }).forEach(function(file) { 
     console.log(file); 
    }); 
}); 
+1

Это бесполезно в его случае. Список упорядочен по алфавиту уже. – AlexanderMP

+0

@AlexanderMP - правда. Эта функция сортировки просто вернет тот же список. – Aukhan

+0

:) Да, я понял. Изменен мой ответ, чтобы преобразовать его в число, а затем отсортировать его – Oxi

0

Вы можете сделать что-то вроде этого:

filesystem.readdirSync('./folder', function(err, files) { 
    files.sort(function(a, b) { 
     a = a.replace(/\w/, ""); //removing 's' or word character 
     b = b.replace(/\w/, ""); 

     return +a - +b; 
    }).forEach(function(file) { 
     console.log(file); 
    }); 
}); 
+1

Обратный вызов sort должен возвращать число <0, 0 или число> 0, а не логическое. –

+0

Спасибо за уведомление. – Xlander

3

Вы можете использовать Array.prototype.sort для сортировки массива по отгонке s и разбору остального как номер:

filesystem = require('fs'); 
var result = filesystem.readdirSync('./folder').sort(function (a, b) { 
    return (+a.substr(1)) - (+b.substr(1)); 
}); 
0
var fs = require('fs'), 
    files = fs.readdirSync('.'), 
    sorted = files.sort(function (a, b) { 
    return Number(a.substr(1)) > Number(b.substr(1)); 
    }); 
console.log(sorted); 
// eg. [ 's0', 's1', 's10', 's100', 's101' ] 
0

Я чувствую, что некоторые из этих ответов wil Я работаю сейчас, ни один из них не подходит для общего случая, поэтому я решил попробовать себя в более общем подходе, который может быть полезен для кого-то другого, который приходит, чтобы прочитать этот вопрос.

function getSort(caseInsensitive) { 
    caseInsensitive = !!caseInsensitive; 
    // Splits a string in to string and number fragments, parsing integers along the way. 
    function getFragments(string) { 
     var strings = string.split(/\d/); 
     var numbers = string.split(/\D/); 
     if (caseInsensitive === true) { 
      strings = strings.map(function(string) { 
       return string.toLowerCase(); 
      }); 
     } 
     // Remove any empty strings (there's likely to be one at the start or at the end). 
     var fragments = strings.filter(function(value) { 
      return value.length > 0; 
     }); 
     var insertIndex = 0; 
     // Insert numbers in the correct place in the fragments array. 
     for (var i = 0; i < numbers.length; i++) { 
      if (numbers[i].length > 0) { 
       fragments.splice(insertIndex, 0, parseInt(numbers[i])); 
       // Add one to insert index to account for the element we just added. 
       insertIndex++; 
      } 
      insertIndex++; 
     } 
     return fragments; 
    } 

    // Actual comparison function. 
    return function(lhs, rhs) { 
     var lhsFragments = getFragments(lhs); 
     var rhsFragments = getFragments(rhs); 

     for (var i = 0; i < lhsFragments.length; i++) { 
      // Sort right-hand-side in front of left-hand-side if left-hand-side has more fragments. 
      if (i >= rhsFragments.length) { 
       return 1; 
      } 
      if (lhsFragments[i] !== rhsFragments[i]) { 
       if (lhsFragments[i] < rhsFragments[i]) { 
        return -1; 
       } else { 
        return 1; 
       } 
      } 
     } 
     // Sort left-hand-side in front of right-hand-side if right-hand-side has more fragments. 
     if (lhsFragments.length < rhsFragments.length) { 
      return -1; 
     } 
     return 0; 
    } 
} 

var caseSensitiveSort = getSort(); 
var caseInsensitiveSort = getSort(true); 
var testArray = [ 
    'x1', 
    'X', 
    'r22s1', 
    'r2s2', 
    's2', 
    'r1t1', 
    'r2', 
    's1t1', 
    's1', 
    's1t2', 
    't', 
    's' 
]; 
console.log(testArray.sort(caseSensitiveSort)); 
console.log(testArray.sort(caseInsensitiveSort)); 

Выходы:

["X", "r1t1", "r2", "r2s2", "r22s1", "s", "s1", "s1t1", "s1t2", "s2", "t", "x1"] 
["r1t1", "r2", "r2s2", "r22s1", "s", "s1", "s1t1", "s1t2", "s2", "t", "X", "x1"] 

Это немного сложнее, конечно, но не чрезмерно. Он также должен обрабатывать многие другие случаи, чем ранее опубликованные ответы, в частности, он не игнорирует фактическое содержимое строки в сравнении. Надеюсь, это будет полезно кому-то.

Смежные вопросы