Linq有条件地扁平不同深度的字符串列表

时间:2016-06-26 18:46:06

标签: c# linq

我有一个对象列表,包含一个字符串, OR 一个字符串列表。我正在尝试提取“扁平”字符串列表。我有一个解决方案,但我想找到一个更好的方法。

以下是创建输入的简单步骤:

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"]

我确定必须有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

您可以尝试将单个值转换为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 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());  

答案 1 :(得分:0)

请尝试以下操作:

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

但首先要做的是考虑你的Foo类设计是否正常,或者你可以改变它(对于一个字符串和列表可能有两个不同的类)以避免这些棘手的问题。