英文:
Custom sort of List<string>
问题
I can provide the translated content:
我有一个 List<string>
,其中条目是位置,如“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<T>
,其中 T
是一个新类。这在这里不相关,因为我处理的是“简单”的字符串。
我还找到了 Enumerable
作为解决方案,但这也不适用,因为可能字符串的列表太大(不可枚举),而且我更喜欢灵活的解决方案。
有人有想法吗?
提前感谢。
英文:
I have a List<string>
, 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<T>
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<string>
:
var input = new List<string>() { "010101", "010102", "010103", "010201", "010202", "020101", "020102", "020201", "020202", "020203", "020204" };
Comparison<string> comparison = (s1, s2) =>
{
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 == "02"
? 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<string>
:
var input = new List<string>() { "010101", "010102", "010103", "010201", "010202", "020101", "020102", "020201", "020202", "020203", "020204" };
Comparison<string> comparison = (s1, s2) =>
{
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 == "02"
? 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<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();
That produces:
010101
010102
010103
010201
010202
020201
020202
020203
020204
020101
020102
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论