Hi,
still dealing with my directory entry lists I have a general question: is it possible to sort a list by two different parameters of the list items in a single step? I just read throush the std.mem.sort... functions but feel a little bit lost understanding the sorting algorithm.
The case: I have an array of data structs. Each data struct represents an item from within a local directory. Thus, in general, every item has a name and can be either a file or a subdir (other types like pipes/sockets etc are left out for now). After collecting the items I want to sort them by two rules:
- Sort directories before files
- Sort directories by name and files by name
However, I’m not able to find out how to achieve this with one sorting operation on the whole list (or even find out if thats possible at all).
Here some example code:
Expand code
const std = @import("std");
const Item = struct {
name: []const u8,
is_dir: bool,
};
fn lessItem(_: void, lhs: Item, rhs: Item) bool {
return std.ascii.orderIgnoreCase(lhs.name, rhs.name) == .lt;
}
pub fn main(init: std.process.Init) !void {
const gpa = init.gpa;
_ = gpa;
var list = [_]Item{
.{ .name = "c_dir", .is_dir = true },
.{ .name = "a_file", .is_dir = false },
.{ .name = "c_file", .is_dir = false },
.{ .name = "a_dir", .is_dir = true },
.{ .name = "b_file", .is_dir = false },
.{ .name = "b_dir", .is_dir = true },
};
std.log.info("Before sorting", .{});
for (list) |i| {
std.debug.print("{s}\n", .{i.name});
}
std.debug.print("\n", .{});
std.mem.sort(Item, &list, {}, lessItem);
std.log.info("After sorting", .{});
for (list) |i| {
std.debug.print("{s}\n", .{i.name});
}
}
The example code produces (ofc because it only sorts by name):
a_dir
a_file
b_dir
b_file
c_dir
c_file
But I want:
a_dir
b_dir
c_dir
a_file
b_file
c_file
For now, to achieve the latter I first collect the code into two separate array lists, one for dirs, one for files, sort every list on its own and only then merge it into the main list. However, that introduces some extra loops. And I would like to reduce this overhead if thats possible (maybe through Context?).