C#根据计算值分组不起作用

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

C# Grouping by calculated values isn't working

问题

这个分组为什么没有正确执行?我按星期和月份进行分组,结果是四个而不是三个。

query.GroupBy(datapoint =>
{
    var timeDimensionValue = (DateTime)datapoint.Dimensions[TimeDimension];
    var keyValues = groupingFunctions.Select(func => func(timeDimensionValue));

    return keyValues.ToArray(); // 例如: { "星期一", 15 };
});

数据:

  • DateTime(2023, 7, 17, 15, 0, 0)
  • DateTime(2023, 7, 19, 7, 0, 0) // 相同
  • DateTime(2023, 7, 19, 7, 0, 0) // 相同
  • DateTime(2023, 7, 21, 11, 30, 0)
英文:

Why isn't this grouping correctly? I'm grouping by day of week and day of month, and I end up with four results, not three.

query.GroupBy(datapoint =>
{
    var timeDimensionValue = (DateTime)datapoint.Dimensions[TimeDimension];
    var keyValues = groupingFunctions.Select(func => func(timeDimensionValue));

    return keyValues.ToArray(); // Ex: { "Monday", 15 };
});

Data:

DateTime(2023, 7, 17, 15, 0, 0)

DateTime(2023, 7, 19, 7, 0, 0) // same

DateTime(2023, 7, 19, 7, 0, 0) // same

DateTime(2023, 7, 21, 11, 30, 0)

答案1

得分: 2

使用数组进行分组不是您想要的,因为数组不会覆盖EqualsGetHashCode方法。您想要根据数组包含的值进行分组。由于您在评论中提到这个数组实际上是一个IList<object>并且是动态的,所以可以包含任何内容,您需要一个可以处理这种情况的自定义比较器:

public class ObjectListComparer: IEqualityComparer<IList<object>>
{
    public bool Equals(IList<object> x, IList<object> y)
    {
        if(x == null && y == null) return true;
        if(x == null || y == null) return false;
        return x.SequenceEqual(y);
    }

    public int GetHashCode(IList<object> obj)
    {
        return string.Join(",", obj?.Select(obj => obj) ?? Enumerable.Empty<object>()).GetHashCode();
    }
}

现在,您可以在GroupBy和许多其他LINQ方法中使用这个比较器:

var groups = data.GroupBy(x => {
    var timeDimensionValue = (DateTime)datapoint.Dimensions[TimeDimension];
    List<object> keyValues = groupingFunctions.Select(func => func(timeDimensionValue));
    return keyValues;
}, new ObjectListComparer());

由于这是一个针对IList<object>的比较器,您可以将其用于您的List<object>以及object[]

英文:

Grouping by an array is not what you want, because arrays don't override Equals and GetHashCode. You want to group by the values the array contains. Since you said in a comment that this array is actually a IList<object> and dynamic, so can contain anything, you need a custom comparer which can handle that:

public class ObjectListComparer: IEqualityComparer<IList<object>>
{
	public bool Equals(IList<object> x, IList<object> y)
    {
		if(x == null && y == null) return true;
		if(x == null || y == null) return false;
        return x.SequenceEqual(y);
    }

    public int GetHashCode(IList<object> obj)
    {
        return string.Join(",", obj?.Select(obj => obj) ?? Enumerable.Empty<object>()).GetHashCode();
    }
}

Now you could use this comparer in GroupBy and many other LINQ methods:

var groups = data.GroupBy(x => {
	var timeDimensionValue = (DateTime)datapoint.Dimensions[TimeDimension];
    List<object> keyValues = groupingFunctions.Select(func => func(timeDimensionValue));
    return keyValues;
}, new ObjectListComparer());

Since it's a comparer for IList<object> you can use it for your List<object> but also for object[].

答案2

得分: 0

你不能像那样对数组进行分组,因为它们没有基于内容的相等语义,只有基于数组引用的相等性。

你可以使用 HashSet,还可以使用 HashSetComparer

query.GroupBy(datapoint =>
{
    var timeDimensionValue = (DateTime)datapoint.Dimensions[TimeDimension];
    var keyValues = groupingFunctions.Select(func => func(timeDimensionValue));

    return keyValues.ToHashSet(); // 例如: { "Monday", 15 };
}, HashSet<object>.CreateSetComparer());

出于性能原因,你可能希望找到一种存储每个集合的实际哈希码的方法。

英文:

You cannot group by arrays like that, as they have no equality semantics based on their contents, only on array reference.

You can use a HashSet instead, along with a HashSetComparer

query.GroupBy(datapoint =&gt;
{
    var timeDimensionValue = (DateTime)datapoint.Dimensions[TimeDimension];
    var keyValues = groupingFunctions.Select(func =&gt; func(timeDimensionValue));

    return keyValues.ToHashSet(); // Ex: { &quot;Monday&quot;, 15 };
}, HashSet&lt;object&gt;.CreateSetComparer());

You may wish to find a way to store the actual hashcode for each set, for performance reasons.

huangapple
  • 本文由 发表于 2023年7月18日 06:31:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76708474.html
匿名

发表评论

匿名网友

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

确定