【问题标题】:Exactly what SelectMany() is for?SelectMany() 到底是干什么用的?
【发布时间】:2016-12-29 05:29:10
【问题描述】:

没有输入和输出很难解释这一点。我做了一个简单的汽车示例,以避免我的项目中不必要的细节。

我有这个清单:

List<car> cars = new List<car>()
{
    new car() { carname = "bmw", carwheels = new List<int>() { 1, 2, 3, 4 } },
    new car() { carname = "cadillac", carwheels = new List<int>() { 1, 2, 3, 4 } },
    new car() { carname = "mustang", carwheels = new List<int>() { 1, 2, 3, 4 } }
};

我想用扩展类输出这个:

{
    { carname = "bmw", carwheel = 1 },
    { carname = "bmw", carwheel = 2 },
    { carname = "bmw", carwheel = 3 },
    { carname = "bmw", carwheel = 4 },
    { carname = "cadillac", carwheel = 1 },
    { carname = "cadillac", carwheel = 2 },
    { carname = "cadillac", carwheel = 3 },
    { carname = "cadillac", carwheel = 4 },
    { carname = "mustang", carwheel = 1 },
    { carname = "mustang", carwheel = 2 },
    { carname = "mustang", carwheel = 3 },
    { carname = "mustang", carwheel = 4 }
}

有没有办法通过 IEnumerable 扩展方法进行投影?与 SelectMany() 相反的东西。

【问题讨论】:

  • 为什么相反,这不正是SelectMany 所做的吗?
  • @TimSchmelter -- 据我了解,SelectMany() 会占据最后的列表并将其压平为单曲,每个单曲都有一个车轮列表。我应该学习 SelectMany() 的另一个重载吗?
  • 这不是SelectMany的反面,这是 SelectMany。
  • 为了完整起见,SelectMany 的“相反”是GroupBy。在这种情况下,您可以 GroupBy carname 的结果,然后为每个组创建一个 car 的实例以获取您的原始列表。
  • @TimSchmelter -- 我明白你的意思。是的,我想我用这个问题的标题误导了所有人。我想我已经看代码太久了:).Rene 的答案正是我所需要的。谢谢!

标签: c# enumerable


【解决方案1】:

这不是SelectMany() 的对立面,而是SelectMany() 的用途。你可以这样实现:

var result = cars.SelectMany(c => 
            c.carwheels.Select(w => new 
            {
                carname = c.carname,
                carwheel = w
            })).ToList();

内部Select 将每辆汽车的轮子投射到一个新对象上(在我的代码中是具有您指定属性的匿名类型)。而外部SelectMany() 将这些序列扁平化为一个列表。

【讨论】:

  • 是的,这让我头疼了一段时间,你说得对——对不起我的误导性标题。这正是我需要的!
【解决方案2】:

这是我发现冗长的 Linq 语法更具可读性的罕见情况之一:

 var query = from car in cars
             from carwheel in car.carwheels
             select new { car.carname, carwheel };

【讨论】:

    【解决方案3】:

    也许这个解决方案会有所帮助?这会将您的 IEnumerable 拆分为固定大小的 IEnumerable

    public static class EnumerableExtension
    {
        private static IEnumerable<T> GetChunk<T>(IEnumerator<T> source, int size)
        {
            yield return source.Current;
    
            for (int i = 1; i < size; i++)
            {
                if (source.MoveNext())
                {
                    yield return source.Current;
                }
                else
                {
                    yield break;
                }
            }
        }
    
        public static IEnumerable<IEnumerable<T>> SplitToChunks<T>(this IEnumerable<T> source, int size)
        {
            if (size < 1)
            {
                throw new ArgumentOutOfRangeException();
            }
    
            using (var enumerator = source.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    yield return GetChunk(enumerator, size);
                }
            }
        }
    
    }
    

    抱歉,没有正确阅读问题)

    【讨论】:

      猜你喜欢
      • 2018-07-27
      • 1970-01-01
      • 2020-05-03
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-19
      相关资源
      最近更新 更多