【问题标题】:Fastest way to get list in custom order按自定义顺序获取列表的最快方法
【发布时间】:2014-08-28 20:37:17
【问题描述】:

我需要找到以自定义顺序获取一小部分字符串或字符的最快方法。 我发现了很多关于对列表进行排序的问题,但在看板或网络上没有关于使用原生类型对小列表进行排序的问题,我发现的只是复杂得多。

对我来说,我的输入列表是字符串列表还是字符列表并不重要。我的列表有 5 - 7 个项目,它们看起来像这样:“1”、“Q”、“A”、“8”、“9”。我想让我的输入按如下顺序排列:“2”、“3”、“4”、“5”、“6”、“7”、“8”、“9”、“1”、“J”, “Q”、“K”、“A”。

我尝试了以下代码:

1 = 3.1-3.5 毫秒:

static readonly List<String> codeValueSortOrder = new List<String> 
{ 
    "2", "3", "4", "5", "6", "7", "8", "9", "1", "J", "Q", "K", "A" 
};
input.OrderBy(i => codeValueSortOrder.IndexOf(i.ToString())).ToList();

2 = 5.0-6.0 毫秒:

input.OrderBy(i => i[1] == 'A')
     .ThenBy(i => i[1] == 'K')
     .ThenBy(i => i[1] == 'Q')
     .ThenBy(i => i[1] == 'J')
     .ThenBy(i => i.Substring(1, i.Length - 1) == "10")
     .ThenBy(i => i[1] == '9')
     .ThenBy(i => i[1] == '8')
     .ThenBy(i => i[1] == '7')
     .ThenBy(i => i[1] == '6')
     .ThenBy(i => i[1] == '5')
     .ThenBy(i => i[1] == '4')
     .ThenBy(i => i[1] == '3')
     .ThenBy(i => i[1] == '2')
     .ToList();

我还在 codeproject 上查看了一些项目,但是这些代码用于数百万个项目,如果我们只想对 5 到 7 个项目进行排序,我无法想象它们是最有效的方法。我的目标是在 0.1 毫秒内执行排序,我不知道是否有可能实现该目标 :)

【问题讨论】:

  • 你能发布你的基准测试代码吗?
  • 这些值总是相同的 7 个值吗?如果是这样,那么您可能只需使用所需顺序的值初始化数组
  • 项目是否可以重复?和@Sayse:op 想要在 5 到 7 个项目之间进行排序,我认为它们是随机的。
  • 是的,这些项目会重复几次,最多重复 4 次。它们是随机的。
  • 无论性能如何,我都不会使用第二种方法。维护噩梦。

标签: c# performance list sorting


【解决方案1】:

您可以使用Dictionary&lt;string, int&gt;,其中键是字符串,值是索引。

您甚至仍然可以使用List&lt;string&gt; 作为基础:

private static readonly List<string> _List = new List<string> { "2", "3", "4", "5", "6", "7", "8", "9", "1", "J", "Q", "K", "A" };
static readonly Dictionary<string, int> Order = _List
    .ToDictionary(str => str, str => _List.IndexOf(str) + 1);

现在您可以使用List.Sort,它不需要在 LINQ 接近时创建新列表:

var input = new List<string> { "1", "Q", "A", "8", "9" };
int i1, i2;
input.Sort((s1, s2) =>
{
    Order.TryGetValue(s1, out i1);
    Order.TryGetValue(s2, out i2);
    return i1.CompareTo(i2);
});

结果顺序:8,9,1,Q,A

快速测试显示:StopWatch.Elapsed.TotalMilliseconds0.0045

Dictionary.TryGetValue 如果找到字符串则返回索引,否则返回 0。这就是为什么我在上面使用_List.IndexOf(str) + 1 来强制找到的物品排在最后。

如果你想要一个降序,你只需要颠倒它:

return i2.CompareTo(i1);

【讨论】:

  • 1 添加到您的 IndexOf 中,您可以跳过三进制(尽管这样您不会通过声明 i1 并将其用作 out 参数中的同一行)。
  • @Rawling:点了。虽然现在如果未找到的项目应该排在最后,更改顺序会更加困难。
  • 是的,这是一个公平的观点。它甚至可能不会对时间产生显着影响。
【解决方案2】:

如果您正在尝试编写高性能扑克代码,您确实需要摆脱字符串/字符表示,并坚持使用 int 0-12 值作为 deuces-aces

您说您的输入是字符串/字符,但在高性能扑克代码中很难找到输入真正是字符/字符串的位置。

如果您尝试解析文本板并弄清楚玩家的手牌,通常表现并不那么重要。

如果你要制作一些详尽的棋盘组合,你真的需要坚持使用整数。

【讨论】:

  • 当你做我做的事情时,你会意识到差异并没有那么大,但我稍后会用 int 测试它,以确保;)
猜你喜欢
  • 2023-01-03
  • 2021-04-02
  • 2012-02-22
  • 1970-01-01
  • 2016-11-18
  • 2019-10-31
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多