如何展平一组数组?

我有一个由以下元素组成的数组:


var schools = new [] {

    new object[]{ new[]{ "1","2" }, "3","4" },

    new object[]{ new[]{ "5","6" }, "7","8" },

    new object[]{ new[]{ "9","10","11" }, "12","13" }

};

我试图展平的真正对象是将数据从 CSV 导入数组数组,然后将其加入字段值:


    var q =

        from c in list

        join p in vocatives on c.Line[name1].ToUpper() equals p.first_name.ToUpper() into ps

        from p in ps.DefaultIfEmpty()

        select new object[] { c.Line,  p == null ? "(No vocative)" : p.vocative, p == null ? "(No sex)" : p.sex }; 

我想展平该字符串数组以获得:


string[] {

    new string[]{ "1","2","3","4" },

    new string[]{ "5","6","7","8" },

    new string[]{ "9","10","11","12","13" }

}

我已经有一个可以循环执行此操作的解决方案,它在性能方面并不那么明智,但它似乎工作正常。


我尝试使用SelectMany但无法提出解决方案。


非常感谢您的反馈;)我尝试过 npo 的回答:


var result = schools.Select(z => z.SelectMany(y=> y.GetType().IsArray 

           ? (object[])y : new object[] { y })

);

但是 CSVwriter 类方法只接受显式类型:


IEnumerable<string[]>

那么如何在linq中做到这一点,我试图:


List<string[]> listOflists = (List<string[]>)result;

InvalidCastException但不幸的是,没有去,出现了。



心有法竹
浏览 208回答 3
3回答

收到一只叮咚

第一步,您必须将数据标准化为一种类型。然后你可以随意迭代它们。因此,首先创建一个方法来将特定点的值展平到任意深度:public static class Extensions{&nbsp; &nbsp; public static IEnumerable<object> FlattenArrays(this IEnumerable source)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; foreach (var item in source)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (item is IEnumerable inner&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; && !(item is string))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (var innerItem in inner.FlattenArrays())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return innerItem;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return item;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}现在您可以在顶层进行迭代以获得所有值的单个数组:// Produces one array => ["1", "2", "3", "4", ...]var allFlat = schools.FlattenArrays().OfType<string>().ToArray();或者您可以创建更深一层的单个数组:foreach (var item in schools){&nbsp; &nbsp; // Produces an array for each top level e.g. ["5", "6", "7", "8"]&nbsp; &nbsp; var flat = item.FlattenArrays().OfType<string>().ToArray();}

慕神8447489

根据评论,由于您的内部数组混合了 and 的元素string[],string因此直接在 Linq 中执行此操作可能并非易事。但是,在辅助函数(我称为Flattener)的帮助下,您可以手动对两种内部类型的处理进行分支,以返回数组中的元素(如果是string[]),或者将单个元素作为可枚举返回,如果不是。SelectMany然后可用于展平内部级别,但您似乎希望保持外级别不展平:IEvar schools = new [] {&nbsp; &nbsp; new object[]{new[]{"1","2"}, "3","4"},&nbsp;&nbsp; &nbsp; new object[]{new[]{"5","6"}, "7","8"},&nbsp; &nbsp; new object[]{new[]{"9","10","11"}, "12","13"}};var result = schools&nbsp; &nbsp; .Select(s => s.SelectMany(o => Flattener(o)));它返回一种类型IEnumerable<IEnumerable<string>>凌乱的拆包位由以下人员完成:public IEnumerable<string> Flattener(object o){&nbsp; &nbsp; if (o is IEnumerable<string> strings)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return strings;&nbsp; &nbsp; }&nbsp; &nbsp; if (o is string s)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp;return new[]{s};&nbsp; &nbsp; }&nbsp; &nbsp; return new[]{"?"};}请注意,上面使用了 C#7 的模式匹配功能。结果截图由 LinqPad 提供:

肥皂起泡泡

如果你想通过 linq 来做,这里有一个示例&nbsp; &nbsp; &nbsp;var schools = new[] {&nbsp; &nbsp; new object[]{new[]{"1","2"}, "3","4"},&nbsp; &nbsp; new object[]{new[]{"5","6"}, "7","8"},&nbsp; &nbsp; new object[]{new[]{"9","10","11"}, "12","13"}};var result = schools.Select(z => z.SelectMany(y=> y.GetType().IsArray ? (object[])y : new object[] { y }));
打开App,查看更多内容
随时随地看视频慕课网APP