You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从两个数组提取唯一字符串?及SQL获取缺勤学生姓名问题

问题解答:提取唯一字符串与缺勤学生查询

1. 如何通过比较两个数组来提取唯一的字符串值?

提取两个数组中独有的字符串,最简洁高效的方式是借助LINQ工具,也可以手动遍历实现,下面给你两种实用方案:

方案一:使用LINQ(推荐)

这种方式代码简洁且性能稳定,需要先引用System.Linq命名空间:

using System.Linq;

// 示例数组
string[] array1 = {"apple", "banana", "cherry", "date"};
string[] array2 = {"banana", "date", "fig", "grape"};

// 获取array1中独有的字符串
string[] uniqueToFirst = array1.Except(array2).ToArray();
// 获取array2中独有的字符串
string[] uniqueToSecond = array2.Except(array1).ToArray();

// 获取两个数组中所有非交集的唯一字符串
string[] allUnique = array1.Union(array2).Except(array1.Intersect(array2)).ToArray();

如果需要忽略大小写匹配,可以添加字符串比较器:

string[] uniqueToFirstIgnoreCase = array1.Except(array2, StringComparer.OrdinalIgnoreCase).ToArray();

方案二:手动遍历实现

如果你不想依赖LINQ,也可以通过集合辅助遍历:

string[] array1 = {"apple", "banana", "cherry", "date"};
string[] array2 = {"banana", "date", "fig", "grape"};

HashSet<string> set2 = new HashSet<string>(array2);
List<string> uniqueToFirst = new List<string>();

foreach (string item in array1)
{
    if (!set2.Contains(item))
    {
        uniqueToFirst.Add(item);
    }
}

string[] result = uniqueToFirst.ToArray();

2. 从SQL数据库中获取缺勤学生姓名的问题

看了你的代码,核心问题大概率出在字符串匹配不一致上——数据库里的RFID值和ListBox中的值可能存在格式差异(比如大小写、前后空格、中间空格数量不同),导致total.Remove(temp)无法正确匹配并移除元素。另外,直接遍历修改total列表的方式遇到重复项时,只会移除第一个匹配项,可靠性不足。

问题分析

  • 数据库中Rfid_Uid是nvarchar(1500)类型,可能存在前后空格,或者字母大小写与ListBox中的内容不一致(比如数据库存42 39 a0 11,ListBox显示42 39 A0 11)
  • 你的代码没有对RFID字符串做格式统一处理,直接进行匹配,自然容易失败

修复后的代码

我给你两种改进方案,优先推荐用LINQ简化逻辑,同时统一字符串格式:

方案一:用LINQ实现更可靠的逻辑

private void checkabst_Click(object sender, EventArgs e)
{
    // 定义统一格式的方法:去除前后空格,转大写,确保匹配一致
    Func<string, string> normalizeRfid = rfid => rfid?.Trim().ToUpper() ?? string.Empty;

    // 获取数据库中所有学生的RFID并统一格式
    List<string> total;
    using (SqlConnection con = new SqlConnection(cs))
    {
        SqlCommand cmd = new SqlCommand("Select Rfid_Uid From Studetails", con);
        con.Open();
        SqlDataReader sdr = cmd.ExecuteReader();
        total = new List<string>();
        while (sdr.Read())
        {
            string rfid = sdr[0].ToString();
            total.Add(normalizeRfid(rfid));
        }
    }

    // 获取ListBox中到校学生的RFID并统一格式
    List<string> present = listbox_present.Items
        .Cast<string>()
        .Select(rfid => normalizeRfid(rfid))
        .ToList();

    // 计算缺勤学生的RFID:total中存在但present中没有的
    List<string> absentRfids = total.Except(present).ToList();

    // 补充获取缺勤学生姓名的逻辑(如果需要的是姓名而非RFID)
    List<string> absentNames = new List<string>();
    using (SqlConnection con = new SqlConnection(cs))
    {
        // 参数化查询避免SQL注入
        string placeholders = string.Join(", ", absentRfids.Select((_, i) => $"@rfid{i}"));
        // 数据库中也统一格式进行匹配
        SqlCommand cmd = new SqlCommand($"Select Name From Studetails Where UPPER(LTRIM(RTRIM(Rfid_Uid))) IN ({placeholders})", con);
        
        for (int i = 0; i < absentRfids.Count; i++)
        {
            cmd.Parameters.AddWithValue($"@rfid{i}", absentRfids[i]);
        }
        
        con.Open();
        SqlDataReader sdr = cmd.ExecuteReader();
        while (sdr.Read())
        {
            absentNames.Add(sdr[0].ToString());
        }
    }

    // 清空缺勤列表再添加新内容
    listbox_absent.Items.Clear();
    foreach (string name in absentNames)
    {
        listbox_absent.Items.Add(name);
    }
}

方案二:修复你原来的遍历逻辑

如果你坚持用原来的遍历方式,记得先统一格式:

private void checkabst_Click(object sender, EventArgs e)
{
    Func<string, string> normalizeRfid = rfid => rfid?.Trim().ToUpper() ?? string.Empty;

    List<string> total = new List<string>();
    using (SqlConnection con = new SqlConnection(cs))
    {
        SqlCommand cmd = new SqlCommand("Select Rfid_Uid From Studetails", con);
        con.Open();
        SqlDataReader sdr = cmd.ExecuteReader();
        while (sdr.Read())
        {
            total.Add(normalizeRfid(sdr[0].ToString()));
        }
    }

    List<string> present = listbox_present.Items
        .Cast<string>()
        .Select(rfid => normalizeRfid(rfid))
        .ToList();

    // 筛选出缺勤的RFID,避免遍历修改列表的问题
    List<string> absent = total.Where(rfid => !present.Contains(rfid)).ToList();

    listbox_absent.Items.Clear();
    foreach (string temp in absent)
    {
        listbox_absent.Items.Add(temp);
    }
}

额外提示

  • 如果最终需要的是缺勤学生的姓名,直接在SQL中查询会更高效,不需要先查所有RFID再对比——比如可以直接查询不在present列表中的学生姓名,减少内存占用和数据传输。
  • 永远记得参数化SQL查询,避免SQL注入风险,上面的代码已经做了参数化处理。
  • 调试时可以打印几个total和present中的元素,快速确认格式是否一致,这是排查这类问题最直接的方式。

内容的提问来源于stack exchange,提问作者Venkatesh Shiga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:04:13