Tuple Array Sorting

Biotronic simen.kjaras at gmail.com
Mon Dec 11 20:58:31 UTC 2017


On Monday, 11 December 2017 at 19:46:04 UTC, Vino wrote:

> import std.algorithm;
> import std.container.array;
> import std.file: SpanMode, dirEntries, isDir ;
> import std.stdio: writefln, writeln;
> import std.typecons: Tuple, tuple;
> import std.range: chain;
>
> void main () {
> auto FFs =  ["C:\\Temp\\BACKUP", "C:\\Temp\\EXPORT", 
> "C:\\Temp\\PROD_TEAM"];
> foreach(d; FFs[]) {
> auto dFiles = Array!(Tuple!(string, SysTime))(dirEntries(d, 
> SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name, 
> a.timeCreated)));
> writefln("%(%-(%-63s %s %)\n%)", chain(dFiles[]).sort!((a, b) 
> => a[1] < b[1]));
> }
> }

So let's go through this code then, shall we?

Edited a bit for clarity:

     // For each directory (*one at a time*),
     foreach(d; FFs[]) {
         // List all the folders
         auto dFiles = Array!(Tuple!(string, SysTime))(
             dirEntries(d, SpanMode.shallow)
                 // Not the files,
                 .filter!(a => a.isDir)
                 // Grab only the information we want,
                 .map!(a => tuple(a.name, a.timeCreated)));
         // And print a sorted list of the subfolders of the 
current folder.
         writefln("%(%-(%-63s %s %)\n%)", 
chain(dFiles[]).sort!((a, b) => a[1] < b[1]));
     }

This will go through C:\Temp\BACKUP, and display a sorted list of 
all the subfolders in that folder. Then it will do the same for 
C:\Temp\EXPORT, and then for C:\Temp\PROD_TEAM.

No subfolder of C:\Temp\PROD_TEAM will be displayed before 
anything in C:\Temp\BACKUP, because you're sorting only one set 
of subfolders at a time.

What you're essentially doing, is sorting [6,2,4] and [3,5,1] 
separately, and printing them separately, giving the illusion of 
having sorted them into the array [2,4,6,1,3,5]. As you correctly 
point out, this is not what you wanted. The code I presented 
avoids this by joining the lists for all the folders.

Your code could also be simplified a bit - there's no need for 
the call to chain, and calling dirEntries.filter.map.array is 
easier to read and write than having Array!(Tuple!(string, 
SysTime)) at the front.

In case my code from earlier was hard to understand, here's 
another version~, more closely modeled to your code:

import std.algorithm : map, filter, sort;
import std.array : array;
import std.file : SpanMode, dirEntries, isDir;
import std.stdio : writefln;
import std.typecons : Tuple, tuple;
import std.datetime : SysTime;

void main() {
     // The folders we want to look in.
     auto folders = [`C:\Windows`, `C:\Program Files`, `C:\Users`];

     // We'll put all the subfolders we find here, so we can sort 
them in the end.
     Tuple!(string, SysTime)[] subFolders;

     // Look through each folder in turn.
     foreach (folder; folders) {
         // Get all entries in the folder,
         auto entries = dirEntries(folder, SpanMode.shallow);
         // Get rid of files,
         auto folderEntries = entries.filter!(a => a.isDir);
         // Grab the interesting parts,
         auto interestingParts = folderEntries.map!(a => 
tuple(a.name, a.timeCreated));
         // And add it to the array.
         subFolders ~= interestingParts.array;
     }
     // Sort the entire array.
     auto sorted = subFolders.sort!((a, b) => a[1] < b[1]);
     // And print it!
     writefln("%(%-(%-63s %s %)\n%)", sorted);
}


More information about the Digitalmars-d-learn mailing list