Introdução
Filtrar arrays – selecionar apenas os elementos que atendem a determinado critério – é uma operação fundamental em qualquer linguagem. Em Zig, não existe uma função filter embutida como em linguagens funcionais, mas é simples implementar filtragem usando loops e ArrayList.
Nesta receita, você aprenderá a filtrar arrays de formas eficientes e reutilizáveis.
Pré-requisitos
- Zig instalado (versão 0.13+). Veja o guia de instalação
- Conhecimento básico de Zig. Consulte a introdução ao Zig
Filtragem Básica com Loop
A forma mais direta de filtrar:
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const numeros = [_]i32{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
// Filtrar números pares
var pares = std.ArrayList(i32).init(allocator);
defer pares.deinit();
for (numeros) |n| {
if (@mod(n, 2) == 0) {
try pares.append(n);
}
}
std.debug.print("Pares: ", .{});
for (pares.items) |n| std.debug.print("{d} ", .{n});
std.debug.print("\n", .{});
// Filtrar maiores que 7
var grandes = std.ArrayList(i32).init(allocator);
defer grandes.deinit();
for (numeros) |n| {
if (n > 7) {
try grandes.append(n);
}
}
std.debug.print("Maiores que 7: ", .{});
for (grandes.items) |n| std.debug.print("{d} ", .{n});
std.debug.print("\n", .{});
}
Saída esperada
Pares: 2 4 6 8 10 12
Maiores que 7: 8 9 10 11 12
Função de Filtro Genérica
Crie uma função reutilizável para filtrar qualquer tipo:
const std = @import("std");
fn filter(
comptime T: type,
allocator: std.mem.Allocator,
items: []const T,
comptime predicate: fn (T) bool,
) ![]T {
var resultado = std.ArrayList(T).init(allocator);
errdefer resultado.deinit();
for (items) |item| {
if (predicate(item)) {
try resultado.append(item);
}
}
return resultado.toOwnedSlice();
}
fn ehPositivo(n: i32) bool {
return n > 0;
}
fn ehPar(n: i32) bool {
return @mod(n, 2) == 0;
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const dados = [_]i32{ -5, 3, -1, 8, 0, -3, 12, 7, -2, 4 };
const positivos = try filter(i32, allocator, &dados, ehPositivo);
defer allocator.free(positivos);
std.debug.print("Positivos: ", .{});
for (positivos) |n| std.debug.print("{d} ", .{n});
std.debug.print("\n", .{});
const pares = try filter(i32, allocator, &dados, ehPar);
defer allocator.free(pares);
std.debug.print("Pares: ", .{});
for (pares) |n| std.debug.print("{d} ", .{n});
std.debug.print("\n", .{});
}
Filtrar Strings
Filtrar uma lista de strings por critério:
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const palavras = [_][]const u8{
"zig", "rust", "go", "c", "java", "python", "lua", "ruby", "zig-brasil",
};
// Filtrar palavras com mais de 3 caracteres
var longas = std.ArrayList([]const u8).init(allocator);
defer longas.deinit();
for (&palavras) |palavra| {
if (palavra.len > 3) {
try longas.append(palavra);
}
}
std.debug.print("Palavras com mais de 3 letras:\n", .{});
for (longas.items) |p| std.debug.print(" - {s}\n", .{p});
// Filtrar palavras que contêm "zig"
var com_zig = std.ArrayList([]const u8).init(allocator);
defer com_zig.deinit();
for (&palavras) |palavra| {
if (std.mem.indexOf(u8, palavra, "zig") != null) {
try com_zig.append(palavra);
}
}
std.debug.print("\nContêm \"zig\":\n", .{});
for (com_zig.items) |p| std.debug.print(" - {s}\n", .{p});
}
Filtrar Structs
Filtrar uma coleção de structs por campo:
const std = @import("std");
const Produto = struct {
nome: []const u8,
preco: f64,
em_estoque: bool,
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const produtos = [_]Produto{
.{ .nome = "Teclado", .preco = 199.90, .em_estoque = true },
.{ .nome = "Monitor", .preco = 1899.00, .em_estoque = false },
.{ .nome = "Mouse", .preco = 89.90, .em_estoque = true },
.{ .nome = "Headset", .preco = 349.90, .em_estoque = true },
.{ .nome = "Webcam", .preco = 459.00, .em_estoque = false },
.{ .nome = "Mousepad", .preco = 49.90, .em_estoque = true },
};
// Filtrar disponíveis e abaixo de R$ 300
var acessiveis = std.ArrayList(Produto).init(allocator);
defer acessiveis.deinit();
for (&produtos) |produto| {
if (produto.em_estoque and produto.preco < 300.0) {
try acessiveis.append(produto);
}
}
std.debug.print("Produtos acessíveis em estoque (< R$300):\n", .{});
for (acessiveis.items) |p| {
std.debug.print(" {s}: R$ {d:.2}\n", .{ p.nome, p.preco });
}
std.debug.print("Total: {d} produtos\n", .{acessiveis.items.len});
}
Saída esperada
Produtos acessíveis em estoque (< R$300):
Teclado: R$ 199.90
Mouse: R$ 89.90
Mousepad: R$ 49.90
Total: 3 produtos
Filtrar In-Place (Sem Alocação Extra)
Quando você pode modificar o array original e quer evitar alocação:
const std = @import("std");
fn filterInPlace(comptime T: type, slice: []T, comptime predicate: fn (T) bool) []T {
var write_idx: usize = 0;
for (slice) |item| {
if (predicate(item)) {
slice[write_idx] = item;
write_idx += 1;
}
}
return slice[0..write_idx];
}
fn maiorQue5(n: i32) bool {
return n > 5;
}
pub fn main() !void {
var dados = [_]i32{ 1, 8, 3, 12, 5, 7, 2, 9, 4, 11 };
const resultado = filterInPlace(i32, &dados, maiorQue5);
std.debug.print("Maiores que 5: ", .{});
for (resultado) |n| std.debug.print("{d} ", .{n});
std.debug.print("\n", .{});
std.debug.print("Quantidade: {d}\n", .{resultado.len});
}
Dicas e Boas Práticas
Use
errdeferao construir resultados: Garanta queArrayListseja liberada em caso de erro durante a construção.toOwnedSlicetransfere propriedade: O chamador fica responsável por liberar a memória retornada.Filter in-place para performance: Quando possível, modifique o slice original para evitar alocações.
Combine com ordenação: Filtre primeiro, depois ordene o resultado para melhor performance.
Receitas Relacionadas
- Arrays Dinâmicos com ArrayList - Base para filtragem
- Ordenar Arrays e Slices - Ordenar resultados filtrados
- Busca Binária - Buscar em dados filtrados
- Como usar HashMap em Zig - Agrupar resultados