惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
J
Java Code Geeks
有赞技术团队
有赞技术团队
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
Microsoft Security Blog
Microsoft Security Blog
IT之家
IT之家
G
Google Developers Blog
月光博客
月光博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
S
SegmentFault 最新的问题
博客园 - 三生石上(FineUI控件)
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
腾讯CDC
V
Visual Studio Blog
博客园 - 【当耐特】
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Engineering at Meta
Engineering at Meta
L
LangChain Blog

博客园 - 我有我奥妙

【BenchmarkDotNet】测试多方式的对象映射 【自动注入】.NET8/.NETCore 依赖注入:自动注入项目中所有接口和自定义类 【排名】处理同分数的排名 【Quartz】.Net8使用定时任务 【模型验证】未被异常捕获到 【Ant Design Vue】相关 【根节点】C#找树形数据的根节点Id 【C#】枚举值 【ECharts】图表自定义显示标题 【消息队列】介绍 【Nginx】Windows部署Vue 设计模式(一)-介绍 【.NetCore】创建本机的静态文件服务器 NLog(一)-使用示例 【nssm】windows上netcore注册为服务 【长路经】C#读取文件抛出FileNotFoundException异常 【RestSharp】常用的几个请求方式 【笔记软件】Obsidian的使用 【浏览器扩展】编写Firefox和Chrome的扩展程序
【字符串排序】C#和前端js排序问题
我有我奥妙 · 2025-01-08 · via 博客园 - 我有我奥妙

前言

前端请求时做了个参数验证,就是简单的计算md5,但是与后端计算的结果始终不一致
发现是前后端对字符串排序的默认规则有区别

测试代码

前端

1、示例代码,可以在浏览器的控制台中直接运行

e=["","你","1","a","d","B","你好","你0","你d","你A",",","你."]
e.sort((a, b) => (a > b ? 1 : a < b ? -1 : 0));
console.log(e);

2、运行结果
['', ',', '1', 'B', 'a', 'd', '你', '你.', '你0', '你A', '你d', '你好']

后端

1、示例代码
var arr = new string[] { "", "你", "1", "a", "d", "B", "你好", "你0", "你d", "你A", ",", "你." };
var r = "'" + string.Join("', '", arr.OrderBy(x => x)) + "'";
Console.WriteLine(r);
2、运行结果
'', ',', '1', '你', '你.', '你0', '你好', '你A', '你d', 'a', 'B', 'd'

分析规则

前端:
空 -> 标点符号 -> 数字 -> 大写字母 -> 小写字母 -> 汉字
后端:
空 -> 标点符号 -> 数字 -> 汉字 -> 字母(不区分大小写)

解决方案

方案1-自定义字符串对比规则

private static void SortByCompare(string[] arr)
{
    var r = string.Join(" ", arr.OrderBy(x => x, new StringComparer()));
    Console.WriteLine(r);
}
public class StringComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        int orderX = 0;
        int orderY = 0;
        if (!string.IsNullOrWhiteSpace(x))
            orderX = GetOrder(x[0]);
        if (!string.IsNullOrWhiteSpace(y))
            orderY = GetOrder(y[0]);
        if (orderX == orderY)
            return string.Compare(x, y, StringComparison.Ordinal);
        return orderX.CompareTo(orderY);
    }
    private int GetOrder(char c)
    {
        if (char.IsPunctuation(c))
            return 10;
        if (char.IsDigit(c))
            return 20;
        else if (char.IsUpper(c))
            return 30;
        else if (char.IsLower(c))
            return 40;
        return 999;
    }
}

方案2-使用V8引擎调用js方法

1、项目添加以下Nuget引用
Microsoft.ClearScript.Core
Microsoft.ClearScript.V8
Microsoft.ClearScript.V8.Native.win-x64
2、项目添加js文件,示例:calc.js,内容如下

function sortParameter(data) {
    if (!data) {
        return "";
    }
    var e = JSON.parse(data);
    e.sort((a, b) => (a > b ? 1 : a < b ? -1 : 0));
    return e.join(" ");
}

3、编写方法

private static V8ScriptEngine _engine = new();
private static void SortByV8(string[] arr)
{
    _engine.Execute(File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "calc.js"), Encoding.UTF8));
    string json = arr.ToJson();
    object r = _engine.Invoke("sortParameter", [json]);
    Console.WriteLine(r);
}

验证

1、后端代码

var arr = new string[] { "", "123", "all", "delay", "Basic", ",./" };
SortByCompare(arr);
SortByV8(arr);

2、后端运行结果
,./ 123 Basic all delay
,./ 123 Basic all delay

3、前端代码

e=["", "123", "all", "delay", "Basic", ",./"]
e.sort((a, b) => (a > b ? 1 : a < b ? -1 : 0));
console.log(e);

4、前端运行结果
['', ',./', '123', 'Basic', 'all', 'delay']

总结

按照这个场景,这2个方案都能实现,但也各有优劣。
方案1-自定义规则,
(1)是C#语言的实现,
(2)但只处理了首个字符的逻辑处理
(3)且未处理汉字的逻辑
方案2-V8引擎调用js
(1)比较重,单独引用了类库
(2)无须重新实现逻辑了,直接执行js的逻辑