Zig NEWS

Andrew Kelley
Andrew Kelley

Posted on

Multi-Object For Loops + Struct-Of-Arrays

Now that the new for loop syntax has landed, there is a pretty cool combination you can do with for loops and std.MultiArrayList:

const std = @import("std");

const S = struct {
    tag: u8,
    data: u32,
};

pub fn main() !void {
    var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    const arena = arena_instance.allocator();

    var list: std.MultiArrayList(S) = .{};

    try list.append(arena, .{ .tag = 42, .data = 99999999 });
    try list.append(arena, .{ .tag = 10, .data = 1231011 });
    try list.append(arena, .{ .tag = 69, .data = 1337 });
    try list.append(arena, .{ .tag = 1, .data = 1 });

    for (list.items(.tag), list.items(.data)) |tag, data| {
        std.debug.print("tag = {d}, data = {d}\n", .{ tag, data });
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

$ zig run test.zig 
tag = 42, data = 99999999
tag = 10, data = 1231011
tag = 69, data = 1337
tag = 1, data = 1
Enter fullscreen mode Exit fullscreen mode

I'll further augment it with some sorting because I think the API is pretty dang cool:

const std = @import("std");

const S = struct {
    tag: u8,
    data: u32,
};

pub fn main() !void {
    var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    const arena = arena_instance.allocator();

    var list: std.MultiArrayList(S) = .{};

    try list.append(arena, .{ .tag = 42, .data = 99999999 });
    try list.append(arena, .{ .tag = 10, .data = 1231011 });
    try list.append(arena, .{ .tag = 69, .data = 1337 });
    try list.append(arena, .{ .tag = 1, .data = 1 });

    const TagSort = struct {
        tags: []const u8,

        pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
            return ctx.tags[lhs_index] < ctx.tags[rhs_index];
        }
    };

    list.sort(TagSort{ .tags = list.items(.tag) });

    for (list.items(.tag), list.items(.data)) |tag, data| {
        std.debug.print("tag = {d}, data = {d}\n", .{ tag, data });
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

$ zig run test.zig 
tag = 1, data = 1
tag = 10, data = 1231011
tag = 42, data = 99999999
tag = 69, data = 1337
Enter fullscreen mode Exit fullscreen mode

The key thing to note here is that, in these examples there are two arrays, one for tag and one for data. These examples demonstrate Zig's ability to manipulate struct-of-arrays with ease.

Top comments (3)

Collapse
 
thdespou profile image
Theo

Awesome. MultiArrayList rocks.

Collapse
 
nathanfranck profile image
Nathan Franck

Zip 'em together and what do you get? Bippity boppity boo

That's awesome!

Collapse
 
chrboesch profile image
Chris Boesch

Why don't you deinitialize the Arena instance with 'defer'?