I have an array with names of files as the entities of the array. I wanted to sort this array based on the size of the files.
For example,
var arr=['index.html','README.md','index.html'];
So what I currently have is that I create an object with name of files as key and size of file as the value.
Now I am fetching these files from a remote location, so I can get the size of the file from content-length
header.
Is there a better way to do it? Will it be possible to do this locally by which I mean read file size and create an object based on that?
I have an array with names of files as the entities of the array. I wanted to sort this array based on the size of the files.
For example,
var arr=['index.html','README.md','index.html'];
So what I currently have is that I create an object with name of files as key and size of file as the value.
Now I am fetching these files from a remote location, so I can get the size of the file from content-length
header.
Is there a better way to do it? Will it be possible to do this locally by which I mean read file size and create an object based on that?
Share Improve this question edited May 21, 2016 at 13:00 Michał Perłakowski 92.9k30 gold badges163 silver badges187 bronze badges asked Jan 11, 2016 at 7:15 Harkirat SalujaHarkirat Saluja 8,1245 gold badges52 silver badges74 bronze badges 1- If you have an object with "name of files as key and size of file as the value" then you can't sort it because Javascript doesn't provide any API for changing the object property order. – Tomáš Zato Commented Jan 11, 2016 at 7:32
4 Answers
Reset to default 4Try this:
var arr = ['index.html','README.md','index.html'];
arr.sort(function(a, b) {
return fs.statSync(a).size - fs.statSync(b).size;
});
I assume that these files are in your current directory.
Short memoized version without promises:
var arr = ['index.html', 'README.md', 'index.html'];
var sortedArray = arr
// get the size of each file
.map(file => { return { file: file, size: fs.statSync(file).size } })
// sort by size ascending
.sort((a, b) => a.size > b.size)
// return a simple sorted array of the file names only
.map(f => f.file);
console.log(sortedArray);
using Bluebird promise, I would do it something like:
var Bluebird = require('bluebird'),
fs = Bluebird.promisifyAll(require('fs')),
arr = [
// your file array
];
// retriving size of each file
function getSize(file){
return fs.statAsync(file).then(stats => stats.size);
}
Promise.all(arr.map( file=> getSize(file).then(size=> {return {file, size}})))
.then(sizedArry => {
console.log(sizedArry);
var sortedArray = sizedArry.sort((a, b) => a.size > b.size); // sorting array based on size
console.log('sorted array: ', sortedArray);
// if you want only the sorted file names...
return sortedArray.map(element => element.file);
});
Expanding on @Gothdo's answer:
var fs = require('fs');
var arr = ['index.html','README.md','index.html'];
function memoize(func) {
var cache = {};
// assumes argument is string
return function memoized(str) {
if (cache[str]) return cache[str];
return (cache[str] = func(str));
};
}
var statSync = memoize(fs.statSync);
arr.sort(function sort(a, b) {
return statSync(a).size - statSync(b).size;
});
Memoizing the function should improve performance of the sorting algorithm, which is quicksort in node, last time I checked.