6

Is there a more idiomatic way of finding if some value is contained in an array than

fn valueInArray(value: u32, array: []const u32) bool {
    for (array) |num| {
        if (value == num) {
            return true;
        }
    }
    return false;
}

2 Answers 2

6

I think that this is generally the most idiomatic solution. It is possible to use containsAtLeast from std.mem, but this seems like an abuse of that function (which is really for finding sequences):

if (std.mem.containsAtLeast(u32, &my_arr, 1, &[_]u32{42})) {
    std.debug.print("Found it!\n", .{});
} else {
    std.debug.print("No secrets found...\n", .{});
}

But I think that the OP posted code could be made more idiomatic by using comptime to allow it to accept types other than u32:

const std = @import("std");

pub fn inSlice(comptime T: type, haystack: []const T, needle: T) bool {
    for (haystack) |thing| {
        if (thing == needle) {
            return true;
        }
    }
    return false;
}

pub fn main() void {
    const my_nums = [_]u32{ 1, 2, 3, 42, 5 };
    const my_chars = [_]u8{ 'a', 'b', 'c', 'X', 'd' };

    // Check for a `u32` in a slice of `u32`:
    if (inSlice(u32, &my_nums, 42)) {
        std.debug.print("Found the secret!\n", .{});
    } else {
        std.debug.print("No secrets found...\n", .{});
    }

    // Check for a `u8` in a slice of `u8`:
    if (inSlice(u8, &my_chars, 'X')) {
        std.debug.print("'X' marks the spot!\n", .{});
    } else {
        std.debug.print("No treasure found...\n", .{});
    }

    // Check for a character in a string:
    if (inSlice(u8, "Marzipan", 'z')) {
        std.debug.print("Found some delicious marzipan!\n", .{});
    } else {
        std.debug.print("No treats for me...\n", .{});
    }
}
> .\find_in_array
Found the secret!
'X' marks the spot!
Found some delicious marzipan!
Sign up to request clarification or add additional context in comments.

Comments

0

Zig endorses an interesting philosophy: only a small set of special types are first-class citizens. If you want to customize a behavior, the utility function must be aware of it.

The for (array) syntax is only applicable to arrays and slices, and the a == b syntax is only applicable to naïve types. If you want to compare strings or structs, you have to roll a special version.

It's up to the user to decide how generic the function wants to be. Clearly, Zig is encouraging the user to specialize over generalize, unless the benefit covers the cost.

So you see, "checking if an element is in an array" can be very complex. What if the collection is not continuous in memory? What if you need a custom equality semantics? What if you need to compare in a specific order? My suggestion is to wait for enough recurring patterns before you generalize to the next degree.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.