用于有条件地平坦化具有不同深度的字符串列表的Linq

本文关键字:深度 字符串 Linq 列表 有条件 用于 | 更新日期: 2023-09-27 17:52:12

我有一个对象列表,包含一个字符串,字符串列表。我正在尝试提取一个"扁平"字符串列表。我有一个解决方案,但我正在努力寻找一个更好的方法。

下面是创建输入的简单步骤:
class Foo
{
    public bool IsArray { get; set; }
    public object Values { get; set; }
} //...    
var innerList = new List<string> {"Inner111", "Inner222"}
var fooList = new List<Foo>();
fooList.Add(new Foo { IsArray = false, Values = "simpleVaue" });
fooList.Add(new Foo { IsArray = false, Values = innerList });

我想要的结果:

["simpleVale","Inner111","Inner222"]

我尝试了几种不同的Linq方法,SelectMany, Aggregate,Select…

var outputListWithWastefulListCreation = 
fooList.SelectMany<Foo, string>(z =>
{
    if (!z.IsArray)
    {
        var wastefulList = new List<string> {z.Values.ToString()};
        return wastefulList;
    }
    var listObject = (IEnumerable<string>) z.Values;
    return listObject;
});

再一次,我期望的结果:

["simpleVale","Inner111","Inner222"]

我相信一定有更好的方法?

用于有条件地平坦化具有不同深度的字符串列表的Linq

您可以尝试将单个值转换为SelectMany中的集合:

 var result = fooList
   .SelectMany(item => item.IsArray
      ? item.Values as List<String>
      : new List<String>() {item.Values as String});

另一个更好的可能性是实现IEnumerable<String> GetValues()' method in the foo ' class:

class Foo
{
    public bool IsArray { get; set; }
    public object Values { get; set; }
    public IEnumerable<String> GetValues() 
    {
      if (null == values)
          yield break;
      List<String> list = Values as List<String>;
      if (list != null)
          foreach (var item in list)
              yield return item;
      else
          yield return Values as String;
    }
}

所以你可以直接写

var result = fooList
   .SelectMany(item => item.GetValues());  

尝试如下:

fooList.SelectMany<Foo, string>(z => z.IsArray ? ((List<string>) z.Values) : new List<string>() {(string) z.Values});

但首先要做的是考虑您的Foo类设计是否ok,或者您可以更改它(可能为一个字符串和列表使用两个不同的类)以避免此类棘手的问题。