AI Library · 知识库

# 筛选与变换:提取已启用用户的邮箱

学习目标:对比函数式链式转换(Filter & Map)与命令式循环收集在各语言中的性能习惯与语法风格。

前置知识与范围:结构体/对象、列表与匿名函数/闭包。演示在内存记录序列上的过滤与字段投影。

# 问题与边界

给定一组用户记录,提取所有**处于激活状态(active == true)**的用户的邮箱地址列表:

# 关键差异

语言 转换惯用风格 语法形态 中间临时集合分配
Rust 惰性迭代器链式消费 .iter().filter(...).map(...).collect() 零中间分配,终结操作一次性收集
Go 显式命令式 for 循环 手写 if u.Active { res = append(...) } 无多余流抽象,性能可控直观
Java Stream API .stream().filter(...).map(...).toList() 惰性求值流管道
JavaScript 原生数组链式方法 users.filter(...).map(...) 产生中间过滤数组
TypeScript 沿用 JS 链式转换 users.filter(...).map(...) 静态字段类型推导保证
Kotlin 扩展函数链式调用 users.filter { it.active }.map { it.email } 默认及早求值产生中间列表
Python 列表推导式(List Comprehension) [u.email for u in users if u.active] 单层字节码直接高效生成结果
C++ 范围循环追加或算法库 范围 for 配合 res.push_back 预留容量(reserve)消除重分配

# 各语言实现

# Rust

Ruststruct User<'a> {
    name: &'a str,
    email: &'a str,
    active: bool,
}

fn extract_active_emails<'a>(users: &[User<'a>]) -> Vec<&'a str> {
    users
        .iter()
        .filter(|u| u.active)
        .map(|u| u.email)
        .collect()
}

fn main() {
    let users = [
        User { name: "Alice", email: "[email protected]", active: true },
        User { name: "Bob", email: "[email protected]", active: false },
        User { name: "Charlie", email: "[email protected]", active: true },
    ];

    let emails = extract_active_emails(&users);
    assert_eq!(emails, vec!["[email protected]", "[email protected]"]);
    assert_eq!(extract_active_emails(&[]), Vec::<&str>::new());

    println!("active: {}", emails.len());
}

Rust 的迭代器适配器是完全惰性的,只有在调用 collect() 时才执行计算。

# Go

Gopackage main

import "fmt"

type User struct {
	Name   string
	Email  string
	Active bool
}

func ExtractActiveEmails(users []User) []string {
	var emails []string
	for _, u := range users {
		if u.Active {
			emails = append(emails, u.Email)
		}
	}
	return emails
}

func main() {
	users := []User{
		{Name: "Alice", Email: "[email protected]", Active: true},
		{Name: "Bob", Email: "[email protected]", Active: false},
		{Name: "Charlie", Email: "[email protected]", Active: true},
	}

	emails := ExtractActiveEmails(users)
	if len(emails) != 2 || emails[0] != "[email protected]" || emails[1] != "[email protected]" {
		panic("mismatch")
	}

	fmt.Printf("active: %d\n", len(emails))
}

Go 社区崇尚简单与透明,虽然可以通过反射或第三方库编写通用流,但显式循环是整个标准库与生态的标准写法。

# Java

Javaimport java.util.List;

public class Main {
    public record User(String name, String email, boolean active) {}

    public static List<String> extractActiveEmails(List<User> users) {
        return users.stream()
                .filter(User::active)
                .map(User::email)
                .toList();
    }

    public static void main(String[] args) {
        List<User> users = List.of(
            new User("Alice", "[email protected]", true),
            new User("Bob", "[email protected]", false),
            new User("Charlie", "[email protected]", true)
        );

        List<String> emails = extractActiveEmails(users);
        assert emails.size() == 2;
        assert "[email protected]".equals(emails.get(0));
        assert "[email protected]".equals(emails.get(1));

        System.out.println("active: " + emails.size());
    }
}

Java 16 的 Stream.toList() 返回不可修改的高性能列表视图。

# JavaScript

JavaScriptconst assert = {
  equal: (a, b) => { if (a !== b) throw new Error(`${a} !== ${b}`); },
  deepEqual: (a, b) => { if (JSON.stringify(a) !== JSON.stringify(b)) throw new Error(`${JSON.stringify(a)} !== ${JSON.stringify(b)}`); },
  throws: (fn, errType) => {
    try { fn(); throw new Error("expected throw"); } catch (e) {
      if (e.message === "expected throw") throw e;
      if (errType && !(e instanceof errType)) throw e;
    }
  }
};

function extractActiveEmails(users) {
  return users
    .filter(u => u.active)
    .map(u => u.email);
}

const users = [
  { name: "Alice", email: "[email protected]", active: true },
  { name: "Bob", email: "[email protected]", active: false },
  { name: "Charlie", email: "[email protected]", active: true },
];

const emails = extractActiveEmails(users);
assert.deepEqual(emails, ["[email protected]", "[email protected]"]);

console.log(`active: ${emails.length}`);

JavaScript 原生数组方法语义高度直观,但需要注意链式调用会生成中间临时数组。

# TypeScript

TypeScriptconst assert = {
  equal: (a: unknown, b: unknown) => { if (a !== b) throw new Error(`${a} !== ${b}`); },
  deepEqual: (a: unknown, b: unknown) => { if (JSON.stringify(a) !== JSON.stringify(b)) throw new Error(`${JSON.stringify(a)} !== ${JSON.stringify(b)}`); },
  throws: (fn: () => void, errType?: unknown) => {
    try { fn(); throw new Error("expected throw"); } catch (e: unknown) {
      if (e instanceof Error && e.message === "expected throw") throw e;
      if (typeof errType === "function" && !(e instanceof errType)) throw e;
    }
  }
};

interface User {
  readonly name: string;
  readonly email: string;
  readonly active: boolean;
}

function extractActiveEmails(users: readonly User[]): string[] {
  return users
    .filter(u => u.active)
    .map(u => u.email);
}

const users: readonly User[] = [
  { name: "Alice", email: "[email protected]", active: true },
  { name: "Bob", email: "[email protected]", active: false },
  { name: "Charlie", email: "[email protected]", active: true },
];

const emails = extractActiveEmails(users);
assert.deepEqual(emails, ["[email protected]", "[email protected]"]);

console.log(`active: ${emails.length}`);

TypeScript 在管道每一步均推断出准确的上下文类型。

# Kotlin

Kotlindata class User(val name: String, val email: String, val active: Boolean)

fun extractActiveEmails(users: List<User>): List<String> {
    return users.filter { it.active }.map { it.email }
}

fun main() {
    val users = listOf(
        User("Alice", "[email protected]", true),
        User("Bob", "[email protected]", false),
        User("Charlie", "[email protected]", true)
    )

    val emails = extractActiveEmails(users)
    check(emails == listOf("[email protected]", "[email protected]"))

    println("active: ${emails.size}")
}

Kotlin 的高阶集合函数提供简洁的内部迭代器语法。若数据量极大可使用 .asSequence() 开启惰性计算。

# Python

Pythonfrom typing import NamedTuple, List

class User(NamedTuple):
    name: str
    email: str
    active: bool

def extract_active_emails(users: List[User]) -> List[str]:
    return [u.email for u in users if u.active]

if __name__ == "__main__":
    users = [
        User("Alice", "[email protected]", True),
        User("Bob", "[email protected]", False),
        User("Charlie", "[email protected]", True),
    ]

    emails = extract_active_emails(users)
    assert emails == ["[email protected]", "[email protected]"]

    print(f"active: {len(emails)}")

Python 社区优先推荐列表推导式,相比 filter() 配合 map() 可读性更好且执行更快。

# C++

C++#include <iostream>
#include <vector>
#include <string>
#include <cassert>

struct User {
    std::string name;
    std::string email;
    bool active;
};

std::vector<std::string> extract_active_emails(const std::vector<User>& users) {
    std::vector<std::string> emails;
    for (const auto& u : users) {
        if (u.active) {
            emails.push_back(u.email);
        }
    }
    return emails;
}

int main() {
    std::vector<User> users = {
        {"Alice", "[email protected]", true},
        {"Bob", "[email protected]", false},
        {"Charlie", "[email protected]", true}
    };

    auto emails = extract_active_emails(users);
    assert(emails.size() == 2);
    assert(emails[0] == "[email protected]");
    assert(emails[1] == "[email protected]");

    std::cout << "active: " << emails.size() << "\n";
}

在 C++17 中,标准范围循环最为直白高效,避免了构建过度复杂的迭代器适配器。

# 迁移误区与适用限制

# 运行与验证

语言版本基线见示例基线。 所有程序运行后控制台输出均为:

纯文本active: 2

筛选条件与提取字段映射断言均已通过。

# 相关阅读