【问题标题】:How do a sort this list on two keys如何在两个键上对这个列表进行排序
【发布时间】:2022-01-06 18:55:07
【问题描述】:
public class Witness
{
    public Mobile m_mobile;
    public bool m_hasLOS;
    public double m_distanceToSqrt;
    public Witness(Mobile m, bool hasLOS, double distanceToSqrt)
    {
        m_mobile = m;
        m_hasLOS = hasLOS;
        m_distanceToSqrt = distanceToSqrt;
    }
}

我已经创建了这些对象“见证”的列表,现在想在 m_hasLOS 和 m_distanceToSqrt 上对其进行排序。

在我的代码中我调用:

List<Witness> sorted = witnesses.OrderBy(x => x.m_hasLOS).ThenBy(x => x.m_distanceToSqrt).ToList();

这可行,但列表没有按我的意愿排序。如何更改排序方式:LOS 始终位于列表顶部,按升序排列? 而在 LOS 为假的情况下,列表只是上升距离?

例如:

o1: m_LOS = true, m_distanceToSqrt = 13
o2: m_LOS = false, m_distanceToSqrt = 6
o3: m_LOS = false, m_distanceToSqrt = 2

应该产生reaultant排序:

o1: m_LOS = true, m_distanceToSqrt = 13
o3: m_LOS = false, m_distanceToSqrt = 2
o2: m_LOS = false, m_distanceToSqrt = 6

【问题讨论】:

  • 请注意,false &lt; true,这就是为什么.OrderByDescending(x =&gt; x.m_hasLOS).ThenBy(x =&gt; x.m_distanceToSqrt)。请注意降序
  • 如果您不想记住是false&lt;true 还是false&gt;true,请将布尔转换为您知道排序方向的东西..OrderBy(x =&gt; x.HasLOS ? 0 : 1)
  • 公共成员的 C# 命名约定是 PascalCase,没有前缀
  • 谢谢你,完美。正是我需要的。 @Caius,是的,我试图通过省略 PascalCase 公共属性来最小化示例大小。
  • 没问题!这确实是一堂恋爱课????。笨蛋

标签: c# list sorting


【解决方案1】:

在 C 语言家族(以及许多其他语言)中,you can think of false as being equal to 0 and true being equal to 1 (more specifically anything that is not 0)

因此,当排序顺序为升序时,对 boolean 字段进行排序将首先返回所有 false 值,因为 0 &lt; 1。如果您首先需要 true 值,则需要使用降序排序。

对于OrderBy,即OrderByDescending。对于ThenBy,即ThenByDescending。在你的情况下,你只需要使用第一个。

List<Witness> sorted = witnesses
    .OrderByDescending(x => x.m_hasLOS)
    .ThenBy(x => x.m_distanceToSqrt)
    .ToList();

Try it out on .NET Fiddle.


旁注,public members should use pascal casingproperties should be preferred over public fields 用于从类职责中抽象实现细节,variable names should favor readability over length

编写类定义的常规方法是:

public class Witness
{
    private Mobile mobile;
    private bool hasLineOfSight;
    private double distanceToSquareRoot;

    public Mobile Mobile 
    {
        get => mobile;
        set => mobile = value;
    }

    public bool HasLineOfSight
    {
        get => hasLineOfSight;
        set => hasLineOfSight = value;
    }

    public double DistanceToSquareRoot
    {
        get => distanceToSquareRoot;
        set => distanceToSquareRoot = value;
    }

    public Witness(Mobile mobile, bool hasLineOfSight, double distanceToSquareRoot)
    {
        Mobile = mobile;
        HasLineOfSight = hasLineOfSight;
        DistanceToSquareRoot = distanceToSquareRoot;
    }
}

由于您的类上没有任何方法,如果它的主要用途是作为值类型,您可以改用 record 类型。

public record Witness(
    Mobile Mobile, 
    bool HasLineOfSight, 
    double DistanceToSquareRoot
);

【讨论】:

    猜你喜欢
    • 2018-09-20
    • 1970-01-01
    • 2013-08-18
    • 2015-04-14
    • 1970-01-01
    • 2012-11-20
    • 2012-12-20
    • 2013-07-29
    • 1970-01-01
    相关资源
    最近更新 更多