第9章 多元化编程场景的智能化实践:从移动端到算法实现

在前八章中,我们深入探讨了桌面应用、Web开发、游戏开发、办公自动化等领域的AI辅助编程。然而,编程的世界远不止于此。移动端开发、数据库操作、正则表达式编写、算法实现等场景同样是开发者日常工作中不可或缺的部分。这些领域各有其独特的挑战:移动开发涉及平台特定的API和生命周期管理,数据库操作需要精确的SQL语法,正则表达式素有“写一次读不懂”的恶名,而算法实现则考验逻辑思维和边界条件处理。

借助ChatGPT和GitHub Copilot,这些领域的开发效率同样可以获得质的飞跃。本章将通过四个典型实例,展示AI如何帮助我们应对这些多元化编程挑战。所有代码均采用Allman风格(左大括号换行),使用驼峰命名法,并确保在VS Code和Android Studio(或VS 2022)中可运行。

9.1 Android开发实例:滑块设置背景色的移动实现

在第5章中,我们实现了桌面版的滑块调色板(PyQt6和C# WinForms)。现在,我们将这一经典案例移植到Android平台,使用Java和Kotlin两种语言实现。通过这个实例,你将看到AI如何辅助理解Android的生命周期、UI布局和事件处理。

9.1.1 需求分析与AI交互

需求描述:开发一个Android应用,界面包含三个SeekBar(滑块)分别控制红、绿、蓝分量,范围为0-255。每个滑块旁显示当前值。界面中央有一个预览区域,其背景色随滑块变化实时更新。同时显示当前颜色的RGB文本和十六进制代码。

向ChatGPT提问:“请用Android Java实现一个调色板应用,界面包含三个SeekBar分别控制RGB,实时更新预览区域的背景色,并显示RGB和十六进制值。”

ChatGPT会给出详细的实现步骤和代码。我们将其整理为可运行的Android项目。

9.1.2 Java实现(Android Studio)

activity_main.xml(布局文件):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <View
        android:id="@+id/colorPreview"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:background="#FF0000" />

    <TextView
        android:id="@+id/rgbText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="RGB: (255, 0, 0)"
        android:textSize="18sp"
        android:layout_marginTop="16dp"/>

    <TextView
        android:id="@+id/hexText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Hex: #FF0000"
        android:textSize="18sp"
        android:layout_marginBottom="16dp"/>

    <!-- 红色滑块 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:textSize="16sp"/>

        <SeekBar
            android:id="@+id/seekBarRed"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:max="255"
            android:progress="255"/>

        <TextView
            android:id="@+id/tvRed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="255"
            android:textSize="16sp"
            android:layout_marginStart="8dp"/>
    </LinearLayout>

    <!-- 绿色滑块 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="8dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="绿"
            android:textSize="16sp"/>

        <SeekBar
            android:id="@+id/seekBarGreen"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:max="255"
            android:progress="0"/>

        <TextView
            android:id="@+id/tvGreen"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:textSize="16sp"
            android:layout_marginStart="8dp"/>
    </LinearLayout>

    <!-- 蓝色滑块 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="8dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:textSize="16sp"/>

        <SeekBar
            android:id="@+id/seekBarBlue"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:max="255"
            android:progress="0"/>

        <TextView
            android:id="@+id/tvBlue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:textSize="16sp"
            android:layout_marginStart="8dp"/>
    </LinearLayout>
</LinearLayout>

MainActivity.java

package com.example.colorpicker;

import android.graphics.Color;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity 
{
    private View colorPreview;
    private TextView rgbText;
    private TextView hexText;
    private TextView tvRed;
    private TextView tvGreen;
    private TextView tvBlue;
    private SeekBar seekBarRed;
    private SeekBar seekBarGreen;
    private SeekBar seekBarBlue;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化视图
        colorPreview = findViewById(R.id.colorPreview);
        rgbText = findViewById(R.id.rgbText);
        hexText = findViewById(R.id.hexText);
        tvRed = findViewById(R.id.tvRed);
        tvGreen = findViewById(R.id.tvGreen);
        tvBlue = findViewById(R.id.tvBlue);
        seekBarRed = findViewById(R.id.seekBarRed);
        seekBarGreen = findViewById(R.id.seekBarGreen);
        seekBarBlue = findViewById(R.id.seekBarBlue);

        // 设置监听器
        SeekBarListener listener = new SeekBarListener();
        seekBarRed.setOnSeekBarChangeListener(listener);
        seekBarGreen.setOnSeekBarChangeListener(listener);
        seekBarBlue.setOnSeekBarChangeListener(listener);

        // 初始更新
        updateColor();
    }

    private void updateColor() 
    {
        int red = seekBarRed.getProgress();
        int green = seekBarGreen.getProgress();
        int blue = seekBarBlue.getProgress();

        // 更新数值显示
        tvRed.setText(String.valueOf(red));
        tvGreen.setText(String.valueOf(green));
        tvBlue.setText(String.valueOf(blue));

        // 更新预览背景色
        int color = Color.rgb(red, green, blue);
        colorPreview.setBackgroundColor(color);

        // 更新文本
        rgbText.setText(String.format("RGB: (%d, %d, %d)", red, green, blue));
        String hex = String.format("#%02X%02X%02X", red, green, blue);
        hexText.setText("Hex: " + hex);
    }

    private class SeekBarListener implements SeekBar.OnSeekBarChangeListener 
    {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) 
        {
            updateColor();
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) 
        {
            // 不需要处理
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) 
        {
            // 不需要处理
        }
    }
}

说明

  • 布局使用LinearLayout和SeekBar。
  • 实现SeekBar.OnSeekBarChangeListener监听滑块变化。
  • updateColor()方法统一更新UI,避免代码重复。
  • 使用Color.rgb()生成颜色。

9.1.3 Kotlin实现与AI辅助

如果使用Kotlin,代码更加简洁。向ChatGPT请求Kotlin版本,它会生成:

package com.example.colorpicker

import android.graphics.Color
import android.os.Bundle
import android.widget.SeekBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() 
{
    private lateinit var colorPreview: View
    private lateinit var rgbText: TextView
    private lateinit var hexText: TextView
    private lateinit var tvRed: TextView
    private lateinit var tvGreen: TextView
    private lateinit var tvBlue: TextView
    private lateinit var seekBarRed: SeekBar
    private lateinit var seekBarGreen: SeekBar
    private lateinit var seekBarBlue: SeekBar

    override fun onCreate(savedInstanceState: Bundle?) 
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 初始化视图
        colorPreview = findViewById(R.id.colorPreview)
        rgbText = findViewById(R.id.rgbText)
        hexText = findViewById(R.id.hexText)
        tvRed = findViewById(R.id.tvRed)
        tvGreen = findViewById(R.id.tvGreen)
        tvBlue = findViewById(R.id.tvBlue)
        seekBarRed = findViewById(R.id.seekBarRed)
        seekBarGreen = findViewById(R.id.seekBarGreen)
        seekBarBlue = findViewById(R.id.seekBarBlue)

        // 设置监听器
        val listener = SeekBar.OnSeekBarChangeListener 
        {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) 
            {
                updateColor()
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {}
            override fun onStopTrackingTouch(seekBar: SeekBar?) {}
        }

        seekBarRed.setOnSeekBarChangeListener(listener)
        seekBarGreen.setOnSeekBarChangeListener(listener)
        seekBarBlue.setOnSeekBarChangeListener(listener)

        updateColor()
    }

    private fun updateColor() 
    {
        val red = seekBarRed.progress
        val green = seekBarGreen.progress
        val blue = seekBarBlue.progress

        tvRed.text = red.toString()
        tvGreen.text = green.toString()
        tvBlue.text = blue.toString()

        val color = Color.rgb(red, green, blue)
        colorPreview.setBackgroundColor(color)

        rgbText.text = "RGB: ($red, $green, $blue)"
        val hex = "#%02X%02X%02X".format(red, green, blue)
        hexText.text = "Hex: $hex"
    }
}

AI辅助的价值:ChatGPT不仅生成了正确的布局和代码,还考虑了Android的最佳实践(如使用findViewById、设置监听器)。开发者只需复制粘贴,稍作调整即可运行。

9.2 数据库操作:创建数据库并编写SQL语句

数据库是应用程序的核心组件之一。编写SQL语句、设计表结构、优化查询是开发者的日常。AI可以帮助生成建表语句、复杂查询、甚至数据库迁移脚本。

9.2.1 使用AI生成SQL建表语句

假设我们需要为一个电商系统设计数据库,包含用户表、商品表、订单表。向ChatGPT描述需求:

“请设计一个电商系统的数据库表结构,包含用户表(users)、商品表(products)、订单表(orders)、订单详情表(order_items)。每个表需要合适的字段和数据类型,并包含主键和外键约束。最后生成SQLite兼容的建表语句。”

ChatGPT会生成类似以下的SQL:

-- 用户表
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL UNIQUE,
    email TEXT NOT NULL UNIQUE,
    password_hash TEXT NOT NULL,
    full_name TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 商品表
CREATE TABLE products (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    description TEXT,
    price DECIMAL(10, 2) NOT NULL,
    stock INTEGER NOT NULL DEFAULT 0,
    category TEXT,
    image_url TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 订单表
CREATE TABLE orders (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    order_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    status TEXT NOT NULL DEFAULT 'pending',
    total_amount DECIMAL(10, 2) NOT NULL,
    shipping_address TEXT,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- 订单详情表
CREATE TABLE order_items (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    order_id INTEGER NOT NULL,
    product_id INTEGER NOT NULL,
    quantity INTEGER NOT NULL,
    unit_price DECIMAL(10, 2) NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

AI辅助的价值:生成的表结构符合第三范式,包含了常用字段和时间戳,并设置了外键。开发者可以在此基础上根据业务需求微调。

9.2.2 编写复杂查询

假设我们需要查询“每个用户的订单总数和总消费金额”,并要求只显示消费超过1000元的用户,按消费金额降序排列。向ChatGPT提问,它会生成:

SELECT 
    u.id,
    u.username,
    COUNT(o.id) AS order_count,
    SUM(o.total_amount) AS total_spent
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username
HAVING total_spent > 1000
ORDER BY total_spent DESC;

如果需要查询“销量最高的前5个商品”,包括商品名称和总销量:

SELECT 
    p.id,
    p.name,
    SUM(oi.quantity) AS total_sold
FROM products p
JOIN order_items oi ON p.id = oi.product_id
GROUP BY p.id, p.name
ORDER BY total_sold DESC
LIMIT 5;

AI辅助的价值:AI正确理解了LEFT JOININNER JOIN的区别,并使用了HAVING过滤聚合结果。

9.2.3 使用Python操作SQLite并插入数据

有了表结构,接下来用Python脚本插入测试数据。向ChatGPT请求:“请用Python编写一个脚本,连接SQLite数据库,创建上述四张表,并插入一些示例数据。”

AI生成的代码(采用Allman风格整理):

import sqlite3
import random
from datetime import datetime, timedelta

class EcommerceDbSeeder:
    """
    电商数据库种子数据生成器
    """
    
    def __init__(self, dbPath='ecommerce.db'):
        """
        初始化数据库连接
        
        Parameters:
            dbPath (str): 数据库文件路径
        """
        
        self.conn = sqlite3.connect(dbPath)
        self.cursor = self.conn.cursor()
        
    def CreateTables(self):
        """创建表结构"""
        
        # 用户表
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT NOT NULL UNIQUE,
                email TEXT NOT NULL UNIQUE,
                password_hash TEXT NOT NULL,
                full_name TEXT,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        
        # 商品表
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS products (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                description TEXT,
                price DECIMAL(10,2) NOT NULL,
                stock INTEGER NOT NULL DEFAULT 0,
                category TEXT,
                image_url TEXT,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        
        # 订单表
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS orders (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER NOT NULL,
                order_date DATETIME DEFAULT CURRENT_TIMESTAMP,
                status TEXT NOT NULL DEFAULT 'pending',
                total_amount DECIMAL(10,2) NOT NULL,
                shipping_address TEXT,
                FOREIGN KEY (user_id) REFERENCES users(id)
            )
        ''')
        
        # 订单详情表
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS order_items (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                order_id INTEGER NOT NULL,
                product_id INTEGER NOT NULL,
                quantity INTEGER NOT NULL,
                unit_price DECIMAL(10,2) NOT NULL,
                FOREIGN KEY (order_id) REFERENCES orders(id),
                FOREIGN KEY (product_id) REFERENCES products(id)
            )
        ''')
        
        self.conn.commit()
        print("表创建成功")
        
    def InsertUsers(self, count=10):
        """插入用户数据"""
        
        users = []
        for i in range(1, count + 1):
            users.append((
                f"user{i}",
                f"user{i}@example.com",
                f"hash{i}",
                f"用户{i}"
            ))
            
        self.cursor.executemany('''
            INSERT INTO users (username, email, password_hash, full_name)
            VALUES (?, ?, ?, ?)
        ''', users)
        self.conn.commit()
        print(f"已插入 {count} 个用户")
        
    def InsertProducts(self, count=20):
        """插入商品数据"""
        
        categories = ['电子产品', '服装', '图书', '家居', '食品']
        products = []
        for i in range(1, count + 1):
            products.append((
                f"商品{i}",
                f"这是商品{i}的描述",
                round(random.uniform(10, 1000), 2),
                random.randint(0, 200),
                random.choice(categories),
                f"http://example.com/product{i}.jpg"
            ))
            
        self.cursor.executemany('''
            INSERT INTO products (name, description, price, stock, category, image_url)
            VALUES (?, ?, ?, ?, ?, ?)
        ''', products)
        self.conn.commit()
        print(f"已插入 {count} 个商品")
        
    def InsertOrders(self, orderCount=30):
        """插入订单和订单详情"""
        
        # 获取所有用户ID和商品ID
        self.cursor.execute("SELECT id FROM users")
        userIds = [row[0] for row in self.cursor.fetchall()]
        
        self.cursor.execute("SELECT id, price FROM products")
        products = [(row[0], row[1]) for row in self.cursor.fetchall()]
        
        # 生成订单
        for _ in range(orderCount):
            userId = random.choice(userIds)
            status = random.choice(['pending', 'paid', 'shipped', 'delivered'])
            
            # 随机生成订单日期(最近30天内)
            daysAgo = random.randint(0, 30)
            orderDate = datetime.now() - timedelta(days=daysAgo)
            
            # 插入订单,先占位total_amount为0
            self.cursor.execute('''
                INSERT INTO orders (user_id, order_date, status, total_amount, shipping_address)
                VALUES (?, ?, ?, 0, ?)
            ''', (userId, orderDate.isoformat(), status, f"地址{userId}"))
            
            orderId = self.cursor.lastrowid
            
            # 随机选择几个商品作为订单项
            itemCount = random.randint(1, 5)
            totalAmount = 0
            
            for _ in range(itemCount):
                productId, price = random.choice(products)
                quantity = random.randint(1, 3)
                unitPrice = price
                totalAmount += unitPrice * quantity
                
                self.cursor.execute('''
                    INSERT INTO order_items (order_id, product_id, quantity, unit_price)
                    VALUES (?, ?, ?, ?)
                ''', (orderId, productId, quantity, unitPrice))
                
            # 更新订单总金额
            self.cursor.execute('''
                UPDATE orders SET total_amount = ? WHERE id = ?
            ''', (totalAmount, orderId))
            
        self.conn.commit()
        print(f"已插入 {orderCount} 个订单")
        
    def Close(self):
        """关闭数据库连接"""
        
        self.conn.close()


def main():
    seeder = EcommerceDbSeeder('ecommerce.db')
    seeder.CreateTables()
    seeder.InsertUsers(5)
    seeder.InsertProducts(10)
    seeder.InsertOrders(20)
    seeder.Close()
    print("数据库初始化完成!")


if __name__ == "__main__":
    main()

说明

  • 使用sqlite3模块。
  • 封装了表创建和数据插入方法。
  • 使用executemany批量插入提高效率。
  • 订单生成考虑了外键约束,先插入父记录再插入子记录。

运行:在VS Code中执行脚本,生成ecommerce.db并填充数据。可用SQLite浏览器查看。

9.3 正则表达式的AI生成与调试

正则表达式(Regex)是处理文本的强大工具,但语法晦涩,调试困难。AI可以根据自然语言描述生成正则表达式,并解释其含义。

9.3.1 常见场景的正则生成

场景1:验证邮箱格式

向ChatGPT提问:“请生成一个用于验证邮箱地址的正则表达式,要求支持常见的邮箱格式,如name@domain.com,域名可以有二级域名如name@domain.co.uk。”

ChatGPT的回答:

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:\.[a-zA-Z]{2,})?$

解释

  • ^ 匹配开头。
  • [a-zA-Z0-9._%+-]+ 用户名部分,允许字母数字及常见符号。
  • @ 字面量。
  • [a-zA-Z0-9.-]+ 域名部分,允许字母数字、点、短横。
  • \. 点号。
  • [a-zA-Z]{2,} 顶级域名至少2个字母。
  • (?:\.[a-zA-Z]{2,})? 可选的二级域名,如.co.uk。
  • $ 匹配结尾。

场景2:提取HTML中的所有图片链接

需求:“请写出正则表达式,从HTML代码中提取所有标签的src属性值。”

AI生成:

<img[^>]*src="([^"]*)"[^>]*>

但考虑到可能单引号或没有引号,更健壮的版本:

<img[^>]*src=['"]([^'"]*)['"][^>]*>

场景3:匹配手机号(中国大陆)

需求:“匹配中国大陆手机号,以1开头,第二位3-9,后面9位数字。”

AI生成:

^1[3-9]\d{9}$

9.3.2 使用Python调试正则表达式

生成的正则需要测试验证。我们可以写一个Python脚本,用re模块测试。

import re

class RegexTester:
    """
    正则表达式测试器
    """
    
    def __init__(self, pattern):
        self.pattern = re.compile(pattern)
        
    def Test(self, testCases):
        """
        测试多个用例
        
        Parameters:
            testCases (list): 列表,每个元素为 (输入字符串, 期望结果)
            
        Returns:
            dict: 测试结果统计
        """
        
        results = []
        for inputStr, expected in testCases:
            match = self.pattern.fullmatch(inputStr) if expected else self.pattern.search(inputStr)
            actual = bool(match)
            results.append({
                'input': inputStr,
                'expected': expected,
                'actual': actual,
                'passed': actual == expected
            })
            
        # 统计
        total = len(results)
        passed = sum(1 for r in results if r['passed'])
        
        return {
            'results': results,
            'total': total,
            'passed': passed,
            'failed': total - passed
        }
        
    def PrintReport(self, testResults):
        """打印测试报告"""
        
        print(f"测试结果: 共 {testResults['total']} 例,通过 {testResults['passed']} 例,失败 {testResults['failed']} 例\n")
        
        for r in testResults['results']:
            status = "✓" if r['passed'] else "✗"
            print(f"{status} 输入: {r['input']:20} 期望: {r['expected']} 实际: {r['actual']}")
            
        if testResults['failed'] > 0:
            print("\n失败用例请检查正则表达式!")


def main():
    # 测试邮箱正则
    emailPattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:\.[a-zA-Z]{2,})?$'
    tester = RegexTester(emailPattern)
    
    testCases = [
        ('test@example.com', True),
        ('user.name+tag@example.co.uk', True),
        ('invalid-email', False),
        ('missing@domain', False),
        ('@domain.com', False),
        ('test@.com', False),
        ('test@domain.c', False)  # 顶级域名至少2字符
    ]
    
    report = tester.Test(testCases)
    tester.PrintReport(report)
    
    # 测试手机号正则
    phonePattern = r'^1[3-9]\d{9}$'
    phoneTester = RegexTester(phonePattern)
    phoneTests = [
        ('13800138000', True),
        ('12345678901', False),  # 第二位不是3-9
        ('1380013800', False),   # 少一位
        ('138001380000', False), # 多一位
        ('23800138000', False)   # 不以1开头
    ]
    
    phoneReport = phoneTester.Test(phoneTests)
    phoneTester.PrintReport(phoneReport)


if __name__ == "__main__":
    main()

AI辅助的价值:AI生成的正则通常准确率较高,但需要测试验证。上述脚本可以快速验证,若有不符,可以将失败用例反馈给AI,让其优化。

9.3.3 复杂正则的分步生成

对于非常复杂的正则,可以分步骤向AI提问。例如,需要匹配一个特定格式的日志行:

2026-05-20 14:30:25 [INFO] User login successful (user_id=12345)

我们可以分步要求AI:

  1. “请写出匹配日期时间部分的正则:yyyy-mm-dd hh:mm:ss”
  2. “匹配日志级别,如INFO、ERROR、WARNING”
  3. “匹配后面的消息,包括括号内的内容”

然后组合起来。AI会给出每一步的表达式,并最终组合。

9.4 算法实现:AI辅助排序与搜索

算法是编程的基础,但实现时容易出错,尤其是边界条件和性能优化。AI可以帮助生成标准算法的代码,并解释其原理。

9.4.1 快速排序的多种实现

向ChatGPT请求:“请用Python实现快速排序算法,要求采用递归方式,并添加详细注释。” AI生成的代码:

def QuickSort(arr, low, high):
    """
    快速排序递归实现
    
    Parameters:
        arr (list): 待排序数组
        low (int): 起始索引
        high (int): 结束索引
    """
    
    if low < high:
        # 分区,获取基准索引
        pi = Partition(arr, low, high)
        
        # 递归排序左右两部分
        QuickSort(arr, low, pi - 1)
        QuickSort(arr, pi + 1, high)
        
def Partition(arr, low, high):
    """
    分区函数,选择最后一个元素作为基准
    
    Parameters:
        arr (list): 数组
        low (int): 起始索引
        high (int): 结束索引
        
    Returns:
        int: 基准元素的最终位置
    """
    
    pivot = arr[high]  # 基准
    i = low - 1        # 较小元素的索引
    
    for j in range(low, high):
        if arr[j] <= pivot:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
            
    # 将基准放到正确位置
    arr[i + 1], arr[high] = arr[high], arr[i + 1]
    return i + 1


def QuickSortWrapper(arr):
    """
    包装函数,方便调用
    
    Parameters:
        arr (list): 待排序数组
        
    Returns:
        list: 排序后的数组(原地排序,返回原数组引用)
    """
    
    QuickSort(arr, 0, len(arr) - 1)
    return arr


if __name__ == "__main__":
    testArr = [10, 7, 8, 9, 1, 5]
    sortedArr = QuickSortWrapper(testArr)
    print("排序结果:", sortedArr)

AI辅助的价值:代码正确实现了快速排序的核心逻辑,注释清晰,易于理解。

9.4.2 二分查找与边界条件

二分查找虽然简单,但边界条件容易出错。向AI请求:“请用Python实现二分查找,要求返回目标值的索引,如果不存在返回-1。同时处理重复元素,返回第一个出现的索引。”

AI生成的代码:

def BinarySearchFirst(arr, target):
    """
    二分查找,返回目标值第一次出现的索引
    
    Parameters:
        arr (list): 已排序的列表
        target: 目标值
        
    Returns:
        int: 索引,若不存在返回-1
    """
    
    left = 0
    right = len(arr) - 1
    result = -1
    
    while left <= right:
        mid = (left + right) // 2
        
        if arr[mid] == target:
            result = mid
            # 继续向左查找,寻找第一个出现
            right = mid - 1
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
            
    return result


def BinarySearchAny(arr, target):
    """
    标准二分查找,返回任意一个匹配的索引
    
    Parameters:
        arr (list): 已排序的列表
        target: 目标值
        
    Returns:
        int: 索引,若不存在返回-1
    """
    
    left = 0
    right = len(arr) - 1
    
    while left <= right:
        mid = (left + right) // 2
        
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
            
    return -1


def TestBinarySearch():
    testCases = [
        ([1, 2, 3, 4, 5], 3, 2),
        ([1, 2, 3, 4, 5], 6, -1),
        ([1, 2, 2, 2, 3], 2, 1),  # 第一个出现的位置应为1
        ([], 5, -1),
        ([1], 1, 0)
    ]
    
    for arr, target, expected in testCases:
        result = BinarySearchFirst(arr, target)
        assert result == expected, f"失败: arr={arr}, target={target}, 期望={expected}, 实际={result}"
        print(f"通过: arr={arr}, target={target} -> {result}")
        

if __name__ == "__main__":
    TestBinarySearch()
    print("所有测试通过!")

AI辅助的价值:AI考虑了重复元素的情况,返回第一个出现的位置,并提供了测试用例验证。

9.4.3 算法复杂度分析

向AI提问:“请分析上面快速排序的时间复杂度和空间复杂度。” AI的回答:

  • 时间复杂度:平均O(n log n),最坏O(n²)(当数组已经有序或逆序时)。
  • 空间复杂度:递归调用栈的深度平均O(log n),最坏O(n)。

9.4.4 使用Copilot实时生成算法

在VS Code中,可以这样利用Copilot:

  • 输入注释 // 实现一个函数,使用动态规划计算斐波那契数列的第n项,Copilot会生成代码。
  • 输入 // 拓扑排序,输入为邻接表,Copilot会给出实现。

9.5 小结

本章通过四个典型的编程场景,展示了AI辅助开发的强大能力:

  • Android开发:AI生成了完整的滑块调色板应用,包括布局和事件处理,帮助开发者快速构建移动端原型。
  • 数据库操作:AI设计了符合范式的表结构,生成了复杂SQL查询,并用Python脚本填充测试数据,展现了从设计到实现的全流程辅助。
  • 正则表达式:AI根据自然语言描述生成正则,并通过测试脚本验证,解决了“写一次读不懂”的痛点。
  • 算法实现:AI提供了快速排序、二分查找的多种实现,包含边界处理和测试用例,确保了代码的正确性。

这些案例表明,无论是平台特定的移动开发,还是通用的数据操作和算法,AI都能成为开发者的得力助手。关键在于:清晰描述需求,结合AI生成的内容进行审查和测试,最终整合到自己的项目中。随着AI能力的不断提升,我们有理由相信,未来的编程将更加智能、高效,开发者可以更专注于创造性的工作,而将重复性的编码任务交给AI。

.

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐