C#|.net core 基础 - 如何判断连续子序列

news/2024/11/15 13:53:17/文章来源:https://www.cnblogs.com/hugogoos/p/18393583

前两天同事遇到了一个小需求,想判断一个集合是不是在另一个集合中存在,并且要求顺序一致,然后一起讨论了下应该怎么做,有没有什么比较好的方式?下面分享一下我们想到的方法,如果你也有不同的想法也可以分享给我。

01解法一:序列化字符串(不推荐)

这个方案的核心思想就是如果一个集合是另一个集合的连续子序列,那么这两个集合序列化成字符串应该也还会有这样的特性,即一个字符串包含了另一个字符串。我立马想到了用string.Join把数组拼接成字符串,具体代码实现如下:

public static bool IsSubsequenceJoin(IEnumerable<string> main, IEnumerable<string> sub)
{var mainString = string.Join(",", main);var subString = string.Join(",", sub);return mainString.Contains(subString);
}

其实听到序列化我第一反应是感觉有坑的,因为序列化会涉及到一些特殊字符的问题,还记得我之前的文章《“hello”.IndexOf(“\0”,2)中的坑》吗,就是因为特殊字符串引起。

当然上面的方法应对大多数需求应该没问题,但是还是有些特例需要注意,比如下面这个例子:

string[] main = ["a", "b", "c", "d,e"];
string[] sub = ["d", "e"];
var isSubsequenceJoin = ContinuousSubsequence.IsSubsequenceJoin(main, sub);
Console.WriteLine("数组 [\"a\", \"b\", \"c\", \"d,e\"] 序列化后: " + string.Join(",", main));
Console.WriteLine("数组 [\"d\", \"e\"] 序列化后: " + string.Join(",", sub));
Console.WriteLine("mainString.Contains(subString) 结果: " + isSubsequenceJoin);

运行结果如下:

因为string.Join使用了“,“作为拼接,所以sub数组序列化后就是"d,e",而数组main中恰好有个元素"d,e",这就导致预期之外的错误结果。

既然string.Join方法有缺陷还有其他序列化方法吗?我们试试专门做序列化的方法JsonConvert.SerializeObject,代码如下:

public static bool IsSubsequenceSerialize(IEnumerable<string> main, IEnumerable<string> sub)
{var mainString = JsonConvert.SerializeObject(main).TrimStart('[').TrimEnd(']');var subString = JsonConvert.SerializeObject(sub).TrimStart('[').TrimEnd(']');return mainString.Contains(subString);
}

这个方法需要我们处理一些序列化产生的额外结构数据,比如上面的TrimStart('[').TrimEnd(']'),就是为了去掉数组产生的额外字符,如果要是其他更复杂类型可以要考虑的情况更多。

当然这个方法就可以解决上面的特例问题,但是依然有些特殊情况会导致错误,比如下面的示例:

string[] main = ["a", "b", "c", "d,\"e"];
string[] sub = ["e"];
var isSubsequenceSerialize = ContinuousSubsequence.IsSubsequenceSerialize(main, sub);
Console.WriteLine("IsSubsequenceSerialize 方法: ");
Console.WriteLine("数组 main [\"a\", \"b\", \"c\", \"d,\\\"e\"] 序列化后: " + JsonConvert.SerializeObject(main).TrimStart('[').TrimEnd(']'));
Console.WriteLine("数组 sub [\"e\"] 序列化后: " + JsonConvert.SerializeObject(sub).TrimStart('[').TrimEnd(']'));
Console.WriteLine("mainString.Contains(subString) 结果: " + isSubsequenceSerialize);

结果如下:

这个例子因为我们在构建数组main时,在一个元素中多加了一个符合[ “ ],使得结果出现预期之外的错误结果。

因此对于序列化字符串方式在大多数情况下都是不推荐使用的,除非你能保证你的数据不会出现一些特殊情况,如果数量大可能还会有性能问题。

02解法二:滑动窗口(推荐)

我们简单解释一下滑动窗口算法是啥意思,先看一下下面这张图感受一下。

滑动窗口可以理解成在一个长轴上,滑动一个窗口,因为窗口大小是固定的,所以随着时间推移,从窗口中看到的东西是不一样的。

把我们的问题和上图结合起来看,如果主数组main代表长轴,子数组sub代表窗口,现在我们把子数组窗口对齐主数组起始位置,然后时间轴每前进一个刻度代表子数组沿着主数组向前移动一位数。

当时间刻度来到T2时,从子数组窗口中可以看到数组[1,3,5],当时间刻度来到T8时,从子数组窗口中可以看到数组[8,7,6]。

也就是说随着时间的推进,当子数组窗口中看到的数组和自身数组值一样时,则代表子数组是主数组的连续子序列。具体实现代码如下:

public static bool IsSubsequenceSlidingWindow<T>(IEnumerable<T> main, IEnumerable<T> sub)
{var mainLength = main.Count();var subLength = sub.Count();for (int i = 0; i < mainLength - subLength + 1; i++){var expect = main.Skip(i).Take(subLength);if (expect.SequenceEqual(sub)){return true;}}return false;
}

注: 相关源码都已经上传至代码库,有兴趣的可以看看。

https://gitee.com/hugogoos/Planner

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/791413.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全网最适合入门的面向对象编程教程:44 Python内置函数与魔法方法-重写内置类型的魔法方法

在 Python 中,内置类型的行为是通过一组特殊的“魔法方法”来实现的,这些魔法方法以双下划线开头和结尾,比如 init 和 str,你可以通过重写这些魔法方法来定制或扩展内置类型的行为。全网最适合入门的面向对象编程教程:44 Python 内置函数与魔法方法-重写内置类型的魔法方法…

软件工程课程第一次个人作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13243这个作业的目标 开始初步学习软件工程,掌握学习的基础和必备条件,为后续学习做准备学号 1022011401.Markdown编辑器2.个人logo…

Python 环境配置(三)安装pytorch

Python 环境配置(三)安装pytorch 一、CUDA 安装CUDA视安装的Pytorch版本而定,GPU版本 需要 安装CUDA,CPU版本 无需 安装CUDA。 1、查看驱动版本 方法一:方法二:2、下载 CUDA Toolkit Archive | NVIDIA Developer选择对应的版本,对应的!!!此后依次选择下载即可注意 wi…

财务知识-合并报表底层逻辑

合并报表如何拆分,如何勾稽,下面两张图教会你!↓

Typora 适配高版本 Mermaid

Typora 适配高版本 Mermaid 查看 Mermaid 版本 info下载最新的 mermaid.min.js文件 在搜索框输入 CDN https://cdn.jsdelivr.net/npm/mermaid@11/替换 Typora 的 window.html 文件 <script>const interval = setInterval(() => {console.log(check mermaid...);if (wi…

工作流之Activiti7 和BPMN讲解

目录1 Activiti1.1 简介1.2 BPMN1.2.1 简介1.2.2 符号1.3 准备工作1.3.1 安装插件1.3.1.1 插件1.3.1.2 本地网页1.3.2 pom依赖1.3.3 添加配置1.3.4 表介绍1.3.5 常用Service服务介绍1.4 无校验操作流程1.4.1 部署&查看文件1.4.1.1 单个文件部署方式1.4.1.2 静态类部署1.4.1…

Python用CNN+LSTM+Attention对新闻文本分类、锂离子电池健康、寿命数据预测

全文链接:https://tecdat.cn/?p=37561 原文出处:拓端数据部落公众号分析师:Weiqiao Jue 在当今的数字化时代,数据的爆炸式增长既带来了机遇,也带来了挑战。如何从海量的数据中高效地提取有价值的信息,并进行准确的分类和预测,成为了众多领域亟待解决的关键问题。 本研究…

【专题】2024年企业数字化人才实践研究报告合集PDF分享(附原数据表)

原文链接:https://tecdat.cn/?p=37556 在当今时代,数字化转型已然成为不可逆转的变革趋势。经过多年的持续发展,中国企业的数字化转型已然迈进了 “深水区”。对于众多企业来说,当下在数字化转型过程中最为迫切需要解决的问题,便是如何在已有的数字化成果基础上进行再度创…

博客内容规范

之前虽然用GitHub Pages建立了个静态博客,但是由于访问速度的问题,我便把内容迁移到了Gitee Pages上,谁能想它直接跑路了,至今还没有发一个字的公告。一波操作,我又迁回了GitHub,但是又想到一个人孤独写博客,还把内容放到GitHub上,访问慢、没人看,更没法和别人交流,感…

platformIO安装过程中速度慢、卡住的解决方法

资源管理器定位到 C:\Users\VSCode安装用户名\.platformio\penv打开pip.conf文件添加如下内容# 超时时间,可自行调整timeout = 6000# 源地址,这里使用阿里云镜像index-url = http://mirrors.aliyun.com/pypi/simple/# 添加源主机为可信主机trusted-host = mirrors.aliyun.com…

C#自定义控件—流动管道

C#用户控件之流动管道 如何绘制一个动态的流动管道(FlowPipe)?分两步绘制定义属性; 画布重绘;主要技能:管道的绘制(渐变色矩形)/// <summary>/// 画渐变色矩形的方法/// </summary>/// <param name="g">画布</param>/// <param n…

swing

数学教材推荐: 中学PDF课本介绍和下载:https://www.zhihu.com/question/517213170/answer/3430923272 swing swing基础 1、容器与控件 1.1)、类介绍JFrame 表示一个窗口JPanel ,表示一个容器,也称为面板JButton,表示一个按钮控件JLabel ,标签控件,用于显示文本1.2)、 使…