gpt4 book ai didi

c# - 在通用列表上模拟 `rollup` 函数

转载 作者:行者123 更新时间:2023-11-30 17:20:44 25 4
gpt4 key购买 nike

例如,我有一个 Element 类型的通用列表。

public class Element
{
public string Country { get; set; }
public string City { get; set; }
public int Population { get; set; }
}

具有以下数据。

var elements = new List<Element>
{
new Element { Country = "Country A", City = "Barrie", Population = 12 },
new Element { Country = "Country A", City = "Barrie2", Population = 12 },
new Element { Country = "Country A", City = "Barrie2", Population = 12 },
new Element { Country = "Country A", City = "Barrie", Population = 12 },
new Element { Country = "Country D", City = "Essex", Population = 12 },
new Element { Country = "Country A", City = "Barrie", Population = 12 },
new Element { Country = "Country A", City = "Barrie", Population = 12 },
new Element { Country = "Country D", City = "Essex", Population = 12 },
new Element { Country = "Country A", City = "Barrie", Population = 12 },
new Element { Country = "Country A", City = "Barrie", Population = 12 }
};

基本上,我想要按国家和城市分组的人口总数。

类似的东西。

Country A | Barrie  | `running total for Barrie`
Country A | Barrie2 | `running total for Barrie2`
| | `total for Country A`
Country D | Essex | `running total for Essex`
| | `total for Country D`
| | `total for everything`

我在任何地方都找不到扩展(我说扩展是因为我计划多次使用汇总)所以我想我会试一试。所以我从这个简单的查询开始。

var groupedElements = elements
.GroupBy(x => new { x.Country, x.City })
.Select(x => new { Country = x.Key, City = x.Select(xx => xx.City), Population = x.Sum(xx => xx.Population) })
.ToList();

此查询按预期工作,所以我认为我走在正确的轨道上。接下来我想我必须弄清楚 groupedElements 中的哪个属性是聚合的,因为这就是我们要对其进行汇总的内容。我如何做到这一点?或者我可以有一个参数,让我指定我希望在哪个列上执行聚合函数。

最佳答案

我认为这并不像您想象的那么容易。首先,您想要的结果序列的项目不是“自然”的同一类型。您需要每个国家/地区的运行总计,每个国家/地区的分组总计,然后是总体总计。

即使您可以编写一个简洁的查询来创建此信息,调用者也必须从结果中区分每种总数。我想知道将您想要的结果作为单个 IEnumerable<XXX> 查看是否有意义首先;创建一个像这样的不错的 OO 解决方案并从那里开始可能更有意义:

public interface IGeographicEnity
{
string Name { get; }
int Population { get; }
}

public class City : IGeographicEntity {...}

public class Country : IGeographicEntity
{
public IList<City> Cities { get {...} }
public int Population { get { return Cities.Sum(c => c.Population); } }
...
}

public class World : IGeographicEntity
{
public IList<Country> Countries { get {...} }
public int Population { get { return Countries.Sum(c => c.Population); }
...
}

如果您仍然想坚持原来的想法,这是我能想到的最好的办法:

public class PopulationTotal
{
// You can use subclassing instead of an enum to represent this
public enum Kind
{ RunningTotalWithinCountry, TotalForCountry, TotalOverall }

public string GroupName { get; private set; }
public int Value { get; private set; }
public Kind Kind { get; private set; }

public static IEnumerable<PopulationTotal> GetTotals(IEnumerable<Element> elements)
{
int overallTotal = 0;

foreach (var elementsByCountry in elements.GroupBy(e => e.Country))
{
int runningTotalForCountry = 0;

foreach (var element in elementsByCountry)
{
runningTotalForCountry += element.Population;
yield return new PopulationTotal
{
GroupName = element.City,
Kind = Kind.RunningTotalWithinCountry,
Value = runningTotalForCountry
};
}

overallTotal += runningTotalForCountry;

yield return new PopulationTotal
{
GroupName = elementsByCountry.Key,
Kind = Kind.TotalForCountry,
Value = runningTotalForCountry
};
}

yield return new PopulationTotal
{
GroupName = null,
Kind = Kind.TotalOverall,
Value = overallTotal
};
}
}

用法:

var totals = PopulationTotal.GetTotals(elements);

关于c# - 在通用列表上模拟 `rollup` 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4048497/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com