【问题标题】:How do I flatten a List<IList>()?如何展平 List<IList>()?
【发布时间】:2016-02-17 23:10:46
【问题描述】:

我有以下属性:

public List<List<MyClass>> Items { get; set;}

这与ListViews ItemSource 绑定,即IEnumerable

就是这个IEnumberableItemSource我现在正在尝试扁平化的属性。

我已设法将其转换为以下内容

this.ItemsSource.Cast<IList>().ToList();

因为以下转换引发了无效转换异常:

this.ItemsSource.Cast<List<object>>().ToList();

我现在希望将此列表扁平化为直接的对象列表。我看了this answer: Flatten List in LINQ 并做了:

this.ItemsSource.Cast<IList>().ToList().SelectMany(x => x);

但这会产生以下错误:

'List' 不包含 'SelectMany' 的定义,并且没有 扩展方法“SelectMany”接受类型的第一个参数 可以找到“列表”(您是否缺少 using 指令或 汇编参考?)

那我做错了什么?是否可以展平List&lt;IList&gt;()

额外信息:

值得一提的是,我使用的是Xamarin,这段代码是我的PCL (portable class library) 的一部分,尽管我确信这不是原因。

在调查这里发生的事情时,我也尝试过:

List<string> s = new List<string>();
s.SelectMany(x => x);

我得到了错误:

方法 'Enumerable.SelectMany(IEnumerable, Func>)' 的类型参数 不能从用法中推断出来。尝试指定类型参数 明确的。

【问题讨论】:

  • 我猜你需要using System.Linq;
  • 我已经为System.Linq命名空间添加了using语句
  • public Items List&lt;List&lt;MyClass&gt;&gt;() { get; set;} 是什么语法... C# 6 中的新东西?
  • @MiguelAngelo 不,只是一个错字。现已修复
  • 如果你这样做:this.ItemsSource.Cast&lt;List&lt;MyClass&gt;&gt;().SelectMany(x =&gt; x); 可以吗?

标签: c# linq list portable-class-library


【解决方案1】:

试试这个:

this.ItemsSource.Cast<IEnumerable>().SelectMany(sublist => sublist.Cast<object>()).ToList()

我用这个示例程序对此进行了测试,它编译并运行:

class Test
{
    public List<List<int>> Items { get; set; }

    public IEnumerable ItemsSource { get { return this.Items; } }

    public List<object> Flatten
    {
        get { return this.ItemsSource.Cast<IEnumerable>().SelectMany(sublist => sublist.Cast<object>()).ToList(); }
    }
}

static class Program
{
    static void Main()
    {
        var t = new Test();
        t.Items = new List<List<int>>
        {
            new List<int> { 1, 2 },
            new List<int> { 11, 12 }
        };

        var r = t.Flatten;
    }
}

我假设,即使您知道项目的类型,但您在使用扁平列表时假装不知道...这就是它返回对象列表而不是整数列表的原因。

【讨论】:

  • 这行得通。谢谢! ItemsSource 是 Lists ItemsSource,因此我不强制转换为特定类型。我很高兴有人相信我,它不像“添加 using 语句”那么简单,谢谢。仍然对你如何得出这个结论感到震惊。我不认为我会解决这个问题
  • 我相信是因为我真的打开了 Visual Studio,创建了一个类,以及一个测试程序......然后我就可以看到问题了。耐心和方法总是有效的!
  • 不要想你自己(“永远无法解决这个问题”)......下次有人问你就会知道。经验就是这样运作的。 =D
【解决方案2】:

先把它转换成正确的类型,然后你可以使用SelectMany

var source = (List<List<MyClass>>) this.ItemsSource;
IEnumerable<MyClass> items = source.SelectMany(list => list);

【讨论】:

    【解决方案3】:

    只要做 -

    var flattened = Items.SelectMany(a => a);
    

    【讨论】:

    • 试过 ItemsSource.SelectMany(x =&gt; x) 并得到以下错误:IEnumerable 不包含 SelectMany 的定义......
    • @user1,答案正确,需要导入System.Linq
    • 这个答案不正确,因为我使用的是ItemsSource 属性,它是IEnumerable,而不是特定类型的Items 类。虽然这段代码可以编译和工作,但它不是问题的答案
    【解决方案4】:

    好的,这里很有趣。这是@TimSchmelters 答案的扩展,解释了为什么转换为正确的类型很重要

    我的第二个错误是:

    方法 'Enumerable.SelectMany(IEnumerable, Func>)' 不能从用法中推断出来。尝试指定类型 显式参数。

    经过一番谷歌搜索,我找到了this answer to the question: "SelectMany() Cannot Infer Type Argument — Why Not?"

    这表明发生此错误的原因如下:

    您传递给 SelectMany 的委托返回的类型必须是 IEnumerable

    所以错误归结为我是如何投射的:

    我必须将其转换为IEnumerable&lt;T&gt;,显然IList 不是这样。如果我执行以下操作,它现在可以工作:

    this.ItemsSource.Cast<IEnumerable<object>>().ToList().SelectMany(x => x);
    

    【讨论】:

      猜你喜欢
      • 2014-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多