自定义排序List

huangapple go评论65阅读模式
英文:

Custom sort of List<string>

问题

I can provide the translated content:

我有一个 List&lt;string&gt;,其中条目是位置,如“010101”,“010102”,“010201”等,具有以下含义:

  • 前两个字符:楼层
  • 接下来的两个字符:通道
  • 最后两个字符:通道中的入口

普通排序会显示以下列表:

010101
010102
010103
010201
010202
020101
020102
020201
020202
020203
020204
...

我想要进行自定义排序,其中:

  • 在楼层“01”上,排序是正常的:

      010101
      010102
      010103
      010201
      010202
    
  • 在楼层“02”上,通道的排序是反向的,但入口通道不变,所以类似于:

      ...
      020201
      020202
      020203
      020204
      020101
      020102
    

在这个网站上,我找到了 IEnumerable 作为解决方案,但这仅适用于 List&lt;T&gt;,其中 T 是一个新类。这在这里不相关,因为我处理的是“简单”的字符串。
我还找到了 Enumerable 作为解决方案,但这也不适用,因为可能字符串的列表太大(不可枚举),而且我更喜欢灵活的解决方案。

有人有想法吗?

提前感谢。

英文:

I have a List&lt;string&gt;, where the entries are locations, like "010101", "010102", "010201", ..., with following meaning:

  • First two characters : floor
  • Next two characters : lane
  • Last two characters : entry in lane

Normal sorting reveals a list like the following:

010101
010102
010103
010201
010202
020101
020102
020201
020202
020203
020204
...

I would like a custom sorting, where:

  • on floor "01", the sorting is done in a normal way:

      010101
      010102
      010103
      010201
      010202
    
  • on floor "02", the sorting is done in a reversed way for the lane, but not for the entry in lane, so something like:

      ...
      020201
      020202
      020203
      020204
      020101
      020102
    

Here on the site, I've found the IEnumerable as a solution, but this only works for List&lt;T&gt; where T is a new class. This is not relevant here, as I'm dealing with "simple" strings.
I've also found the Enumerable as a solution, but this also doesn't work, because the list of possible strings is far too large (not enumerable) and I'd prefer a flexible solution.

Does anybody have an idea?

Thanks in advance

答案1

得分: 4

以下是您要翻译的内容:

有多种实现所需行为的方式,例如使用 Comparison&lt;string&gt;

var input = new List&lt;string&gt;() { &quot;010101&quot;, &quot;010102&quot;, &quot;010103&quot;, &quot;010201&quot;, &quot;010202&quot;, &quot;020101&quot;, &quot;020102&quot;, &quot;020201&quot;, &quot;020202&quot;, &quot;020203&quot;, &quot;020204&quot; };

Comparison&lt;string&gt; comparison = (s1, s2) =&gt;
{
    if (s1 == null) throw new ArgumentNullException(nameof(s1));
    if (s2 == null) throw new ArgumentNullException(nameof(s2));
    if (s1.Length != 6 || s2.Length != 6) throw new ArgumentOutOfRangeException();

    // 比较楼层(前两位数字)
    var floor1 = s1.Substring(0, 2);
    var floor2 = s2.Substring(0, 2);
    var result = floor1.CompareTo(floor2);
    if (result != 0) return result;

    // 比较车道(中间两位数字)
    var lane1 = s1.Substring(2, 2);
    var lane2 = s2.Substring(2, 2);
    // 特殊情况:在02楼,反转车道顺序
    result = floor1 == &quot;02&quot;
       ? lane2.CompareTo(lane1) 
       : lane1.CompareTo(lane2);
    if (result != 0) return result;

    // 比较入口(最后两位数字)
    return s1.Substring(4, 2).CompareTo(s2.Substring(4, 2));
};

// 使用之前定义的比较函数对列表进行排序
input.Sort(comparison);
英文:

There are multiple ways to achieve the desired behavior, e.g. using a Comparison&lt;string&gt;:

var input = new List&lt;string&gt;() { &quot;010101&quot;, &quot;010102&quot;, &quot;010103&quot;, &quot;010201&quot;, &quot;010202&quot;, &quot;020101&quot;, &quot;020102&quot;, &quot;020201&quot;, &quot;020202&quot;, &quot;020203&quot;, &quot;020204&quot; };

Comparison&lt;string&gt; comparison = (s1, s2) =&gt;
{
	if (s1 == null) throw new ArgumentNullException(nameof(s1));
	if (s2 == null) throw new ArgumentNullException(nameof(s2));
	if (s1.Length != 6 || s2.Length != 6) throw new ArgumentOutOfRangeException();

	// Compare floor (first 2 digits)
	var floor1 = s1.Substring(0, 2);
	var floor2 = s2.Substring(0, 2);
	var result = floor1.CompareTo(floor2);
	if (result != 0) return result;

	// Compare lane (middle 2 digits)
	var lane1 = s1.Substring(2, 2);
	var lane2 = s2.Substring(2, 2);
    // Special case: in floor 02, reverse order of lanes
    result = floor1 == &quot;02&quot;
       ? lane2.CompareTo(lane1) 
       : lane1.CompareTo(lane2);
	if (result != 0) return result;

	// Compare entry (last 2 digits)
	return s1.Substring(4, 2).CompareTo(s2.Substring(4, 2));
};

// Sort the list using the comparison defined before
input.Sort(comparison);

答案2

得分: 1

以下是翻译好的部分:

如果您的输入已经很好地筛选(即全部是数字并且都是6个字符),那么这是一个简单的方法来执行:

var input = new List<string>()
{
    "010101", "010102", "010103", "010201", "010202",
    "020101", "020102", "020201", "020202", "020203", "020204"
};

var output =
    input
        .Select(x => new
        {
            location = x,
            floor = int.Parse(x.Substring(0, 2)),
            lane = int.Parse(x.Substring(2, 2)),
            entry = int.Parse(x.Substring(4, 2))
        })
        .OrderBy(x =>
            x.floor * 10000
            + (x.floor % 2 == 0 ? 99 - x.lane : x.lane) * 100
            + x.entry)
        .Select(x => x.location)
        .ToList();

这将产生以下结果:

010101 
010102 
010103 
010201 
010202 
020201 
020202 
020203 
020204 
020101 
020102 

希望这对您有所帮助。

英文:

If your input is nicely curated (i.e. all numerals and all 6 characters) then this is a simple way to do it:

var input = new List&lt;string&gt;()
{
	&quot;010101&quot;, &quot;010102&quot;, &quot;010103&quot;, &quot;010201&quot;, &quot;010202&quot;,
	&quot;020101&quot;, &quot;020102&quot;, &quot;020201&quot;, &quot;020202&quot;, &quot;020203&quot;, &quot;020204&quot;
};

var output =
	input
		.Select(x =&gt; new
		{
			location = x,
			floor = int.Parse(x.Substring(0, 2)),
			lane = int.Parse(x.Substring(2, 2)),
			entry = int.Parse(x.Substring(4, 2))
		})
		.OrderBy(x =&gt;
			x.floor * 10000
			+ (x.floor % 2 == 0 ? 99 - x.lane : x.lane) * 100
			+ x.entry)
		.Select(x =&gt; x.location)
		.ToList();

That produces:

010101 
010102 
010103 
010201 
010202 
020201 
020202 
020203 
020204 
020101 
020102 

huangapple
  • 本文由 发表于 2023年4月17日 14:31:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76032253.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定