1

我正在尝试获取按修改时间排序的目录内容。我认为没有办法直接在dirEntries调用中执行此操作,因此我的策略是收集所有文件时间和名称,然后对两个数组进行同步排序。

问题 1:我不知道如何将 asysTime转换为整数。
问题 2:我不知道如何对两个数组进行并行排序。

与 D 中的每个问题一样,不可能找出如何做到这一点:(

这是我的代码:

import std.file;
import std.stdio : writeln;
import std.algorithm;
import std.datetime;

void main() {
    string[] myFiles;
    double[] myTimes;

    foreach (DirEntry e; dirEntries("c:/users/istaffel/", SpanMode.shallow)) {
        // calculate unix time (this doesn't work)
        auto dur = (cast(Date)e.timeLastModified) - Date(1970,1,1);

        // store modified time and filename
        myTimes ~= dur.seconds;
        myFiles ~= e.name;
    }

    // now find a way to sort myFiles in order of ascending myTimes...

    // print in order
    for (int i = 0; i < myTimes.length; i++) {
        writeln(myTimes[i], " ", myFiles[i]);
    }
}
4

1 回答 1

8

一般来说,除非您正在与 C 交互,否则我建议将其转换SysTime为整数值是一个坏主意(并且将其转换double为更糟)。但是,如果您真的需要将其转换为time_t您似乎正在做的事情,那么只需使用SysTime'stoUnixTime函数:

auto timeT = e.timeLastModified.toUnixTime();

做你想做的事情的最简单的解决方案是

import std.algorithm;
import std.array;
import std.datetime;
import std.file;
import std.stdio;

void main(string[] args)
{
    auto directoryToList = args[1];
    auto files = array(dirEntries(directoryToList, SpanMode.shallow));
    sort!"a.timeLastModified < b.timeLastModified"(files);
    foreach(file; files)
        writefln("%s %s", file.timeLastModified, file.name);
}

如果你真的想要一个time_t,那就去做吧file.timeLastModified.toUnixTime()

dirEntries返回一个范围,因此您可以对其进行迭代并直接对其进行操作,但是为了对其进行排序,您需要一个随机访问范围(结果dirEntries不是,因为它懒惰地访问文件)。因此,您可以使用std.array.array它来创建一个数组,然后对其进行排序。sort接受一个谓词(无论是使用 std.functional 转换为函数的字符串、lambda 文字、委托、函数指针,还是任何可使用您正在排序的类型的两个参数调用的东西 - 在这种情况下,我使用了一个字符串,在下面的示例中,我将 lambda 文字用于map)。

如果您正在处理大量文件并希望最大限度地减少使用的内存量(因为DirEntry确实有几个成员变量,因此如果您关心所有这些,那么它们的数组可能会占用比您想要的更多的内存是文件的名称和修改时间),那么它会变得更有趣,但它仍然很可行。

import std.algorithm;
import std.array;
import std.datetime;
import std.file;
import std.stdio;
import std.typecons;

void main(string[] args)
{
    auto directoryToList = args[1];
    auto files = dirEntries(directoryToList, SpanMode.shallow);
    auto pairs = array(map!(a => tuple(a.timeLastModified, a.name))(files));
    sort!"a[0] < b[0]"(pairs);
    foreach(pair; pairs)
        writefln("%s: %s", pair[0], pair[1]);
}

再说一次,如果你真的想要一个time_t,就做那个pair[0].toUnixTime()

这最终创建了一个仅包含时间和名称的元组数组,然后仅使用时间对这些元组进行排序

如果您对范围不是很熟悉,那么我建议您从有关 D 的标准库的在线书籍中阅读本章。D 的标准库大量使用范围,这可能是您觉得很难弄清楚如何在 D 中做事。范围是一个非常强大的概念,但它们确实需要一些时间来适应。

于 2013-03-06T18:40:29.403 回答