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

Linq Distinct方法异常:仅修改字符串后计数结果才正确

问题原因与解决方案

你的问题核心是字符串的默认相等比较没有忽略隐藏的不可见字符,导致肉眼看起来不同的LocationID被Distinct()错误判定为相等;而调用Reverse()后,这些隐藏字符的位置发生变化,反转后的字符串差异显现,Distinct()就能正确区分了。

具体分析

你看到的B A01A和A A01A看似只有首字符不同,但实际其中一个(或两个)字符串可能包含:

  • 首尾的换行符、回车符、制表符(\r/\n/\t)
  • 全角空格、不间断空格(\u00A0)这类肉眼难辨的空白字符

默认的Distinct()使用字符串的严格值相等比较,会把这些隐藏字符纳入比较逻辑,错误地将两个字符串判定为相等,导致计数为1。而Reverse()会把这些隐藏字符移到字符串的另一端,使得反转后的字符串(比如A10A B\n和A10A A)差异明显,Distinct()就能正确识别出两个不同值。

解决方法

1. 先排查字符串实际内容

用代码输出带转义的字符串内容,定位隐藏字符:

foreach (var alloc in orderLine.OrderAllocations.Where(y => y.StatusID != 250))
{
    Console.WriteLine($"LocationID: '{alloc.LocationID}', 长度: {alloc.LocationID.Length}, 转义后: {System.Text.RegularExpressions.Regex.Escape(alloc.LocationID)}");
}

通过输出的转义字符(比如\r、\u00A0)确认问题根源。

2. 清理字符串后再去重

针对排查出的隐藏字符,先清理LocationID再调用Distinct():

var result = rootObject.OrderLines.Where(orderLine =>
orderLine.OrderAllocations
    .Where(y => y.StatusID != 250) 
    .Select(y => 
        // 去除首尾空白,替换特殊空白为普通半角空格,移除换行/回车
        y.LocationID.Trim()
                    .Replace("\u00A0", " ")
                    .Replace("\t", " ")
                    .Replace("\r", "")
                    .Replace("\n", "")
    )  
    .Distinct() 
    .Count() == 2); // 注意原代码中判断条件是==1,需根据实际需求修正

3. 自定义相等比较器(更灵活)

如果需要复用清理逻辑,可以自定义字符串比较器,传给Distinct():

public class LocationEqualityComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        
        var cleanedX = CleanLocationString(x);
        var cleanedY = CleanLocationString(y);
        
        return cleanedX.Equals(cleanedY, StringComparison.Ordinal);
    }

    public int GetHashCode(string obj)
    {
        return obj == null ? 0 : CleanLocationString(obj).GetHashCode();
    }

    private string CleanLocationString(string input)
    {
        return input.Trim()
                    .Replace("\u00A0", " ")
                    .Replace("\t", " ")
                    .Replace("\r", "")
                    .Replace("\n", "");
    }
}

// 使用示例
var result = rootObject.OrderLines.Where(orderLine =>
orderLine.OrderAllocations
    .Where(y => y.StatusID != 250) 
    .Select(y => y.LocationID)  
    .Distinct(new LocationEqualityComparer()) 
    .Count() == 2);

内容的提问来源于stack exchange,提问作者Nasim Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:34:51