我想对一些数据进行有效的排序。假设我有这个字符串列表:
var somedata = new List<string> {"<some data>",
" <some data else>",
"</some data>",
"<Animal>",
" <Animal Name=\"Lion\" Group=\"Feline\" Colour=\"Brown\" />",
" <Animal Name=\"Zebra\" Group=\"Equidae\" Colour=\"Black and White\" />",
" <Animal Name=\"Tuna\" Group=\"Fish\" Colour=\"Gray\" />",
" <Animal Name=\"Horse1\" Group=\"Equidae\" Colour=\"Black\" />",
" <Animal Name=\"Horse10\" Group=\"Equidae\" Colour=\"White\" />",
" <Animal Name=\"Horse2\" Group=\"Equidae\" Colour=\"White\" />",
" <Animal Name=\"Dog20\" Group=\"Canidae\" Colour=\"Black\" />",
" <Animal Name=\"Dog2\" Group=\"Canidae\" Colour=\"Black\" />",
" <Animal Name=\"Cat\" Group=\"Feline\" Colour=\"Various\" />",
" <Animal Name=\"Falcon\" Group=\"Bird 1\" Colour=\"Brown\" />",
" <Animal Name=\"Duck\" Group=\"Bird 2\" Colour=\"White\" />",
" <Animal Name=\"Eagle\" Group=\"Bird 1\" Colour=\"Brown\" />",
" <Animal Name=\"Shark\" Group=\"Fish\" Colour=\"Gray\" />",
" <Animal Name=\"Mouse\" Group=\"Rodent\" Colour=\"Brown\" />",
"</Animal>",
"<some other data>"
" <bla bla bla>"
"</some other data>"};
实际上,我用这个简单的方法来排序
somedata.Sort();
然后我把它们复制到一个新的列表中迭代Group=
的列表(猫科,马科,鱼类,猫科,鸟类1,Bird2…)参数,因为我会按组类型划分列表。在第二个新列表中没有AnimalName
,然后我在标记"<Animal>"
和"</Animal>"
之间使用命令templist.Add(line)
进行合并。(这里不会有双字符串,因为我复制了所有的数据,而没有后面复制的要排序的数据)。
好吧,我们可以说我遵循的方式在99%(我有数字问题),但我想直接使用Sort()。我如何为参数<Animal Name=
和Group=
创建一个自定义排序过滤器,留下任何没有<Animal Name=
的字符串?
顺便说一句,当我用我现在的方法排序时,我发现了一个问题。带有数字的数据不遵循语法顺序规则,所以我得到了Horse1
,Horse10
和Horse2
,而不是我想得到的:Horse1
、Horse2
和Horse10
。
如何解决最后一个问题?
先谢谢你了
输出结果如下所示:
<some data>
<some data else>
</some data>
<Animal>,
<Animal Name="Eagle" Group="Bird 1" Colour="Brown" />
<Animal Name="Falcon" Group="Bird 1" Colour="Brown" />
<Animal Name="Duck" Group="Bird 2" Colour="White" />
<Animal Name="Dog2" Group="Canidae" Colour="Black" />
<Animal Name="Dog20" Group="Canidae" Colour="Black" />
<Animal Name="Horse1" Group="Equidae" Colour="Black" />
<Animal Name="Horse2" Group="Equidae" Colour="White" />
<Animal Name="Horse10" Group="Equidae" Colour="White" />
<Animal Name="Zebra" Group="Equidae" Colour="Black and White" />
<Animal Name="Cat" Group="Feline" Colour="Various" />
<Animal Name="Lion" Group="Feline" Colour="Brown" />
<Animal Name="Shark" Group="Fish" Colour="Gray" />
<Animal Name="Tuna" Group="Fish" Colour="Gray" />
<Animal Name="Mouse" Group="Rodent" Colour="Brown" />
</Animal> />
<some other data>
<bla bla bla>
</some other data>
2条答案
按热度按时间ndh0cuux1#
要在
horse2
之后对horse10
进行排序,请参阅natural sort order in c#。您可以通过调用本机函数并将其 Package 在IComparer中来使用与windows相同的排序:然而,尝试像这样对字符串进行排序而不实际解析它们似乎非常脆弱。由于数据似乎是某种XML,我建议使用某种类型的XML解析将其转换为对象列表。如果您想根据多个属性对对象进行排序,可以使用LINQ
.OrderBy(...)
和.ThenBy(...)
。bttbmeg02#
从纯粹的 * 排序 * Angular 来看,这个请求的问题是,您只要求按多个维度对列表中的项目的子集进行排序,但希望在更大的集合中保持该子集的一般位置。
我们不能用
Array.Sort()
或自定义IComparable
实现以确定性的方式实现这一点,因为外部集需要保持其原始的任意序列,而序列信息不包含在字符串值本身中。但是我们可以用LINQ来做这件事。
我想高效地分类
你的意思是你想要最少的代码,或者最少的迭代,或者最少的执行时间,或者最少的内存使用量?
认识到这个字符串列表一起形成了许多XML元素意味着我们可能会反序列化为对象,重新处理数据,然后重新序列化回字符串列表。这在代码和时间方面很可能是效率最低的,但会产生最可靠的结果,逻辑也会简单得多理解。内存消耗应该是可管理的...只要您能保证输入是有效的XML片段,这个(在撰写本文时)就不是
你的第一次尝试并不坏,但它会导致然而,有一种技术,不涉及维护单独的孤立的记录列表。我们可以将数据分类(归类)到分组集合中,这样我们就可以根据这些集合中的组或值的索引进行排序,而无需实际存储它们或修改原始字符串。
首先,让我们来处理数字排序。我发现最简单的解决方案是用零填充所有数值到一个固定的长度,下面的方法接受一个字符串和在字符串中找到的任何数字将被填充到的位数。
这个逻辑使用分类技术来识别文本中的数字,我们确定这些组是全数字或全字母(当然不是数字)的字符,并为每个组分配一个索引。然后,我们可以使用LINQ组表达式根据这些索引进行分组,并在数字组中使用左填充。
在此答案中使用此解决方案而不是PInvoke:https://stackoverflow.com/a/75986862/1690217
您可以test this here:
生成以下输出:
回到最初的问题...
因此,排序顺序需要如下:
1.对于所有不以
<Animal Name=
开头的项目,请遵循原始的整体顺序1.按 Animal 项中的
Group=
属性值排序Name=
属性排序我们以同样的方式来实现这一点,使用LINQ projection(Select)来 classify 我们的分组集,然后在组上使用LINQ sort (OrderBy)来实现所需的排序层次结构:https://dotnetfiddle.net/707YIW
对于那些仔细看过或者刚接触LINQ的人来说,你可以看到我使用了一个overload of Select来从底层枚举器中公开索引。这就是我们如何访问整个序列,而不需要先故意迭代整个集合。
这解决了
Array.Sort
和IComparable
不能解决的问题,如果我们不以这种方式使用IEnumerable.Select
,那么我们将不得不使用for
循环来迭代这些项...以下输出包括分类数据,因此您可以看到它是如何工作的:
这个排序逻辑对于这个特定的输入是如此独特,以至于尝试将排序逻辑打包到
IComparable
实现中几乎没有价值,即使你可以。然而,IEnumerable
逻辑可以抽象为一个自定义的Enumeration,它看起来很漂亮,但这并没有使代码更容易维护,相反,它对用户隐藏了逻辑,这可能会对您的团队产生负面影响。的能力,以理解和维护这一逻辑在长期内:https://dotnetfiddle.net/lxI16F用法,接近
.Sort()
:注意事项:
List<string>
的扩展公开是没有意义的,因为实现太具体了。您可以对某种业务域类型这样做,但不能对字符串列表这样做,这将是一种反模式。LexicographicToAlphaNumeric
的默认size
实现,或者为size
参数提供一个值如果不首先解析 ALL 可能的值,我们就无法知道函数内部的最大长度是多少,这将不会那么有效。