【问题标题】:How to combine all strings in a nested-list?如何组合嵌套列表中的所有字符串?
【发布时间】:2014-02-16 13:07:13
【问题描述】:

我有一个列表,其中包含多级嵌套列表。每个列表都可以有字符串和其他类型的实例。

例如

var list = [ 'a', 'w', ['e', ['f', new Object(), 'f'], 'g'], 't', 'e'];

我想写一个函数(比如compress)来组合字符串和它们的兄弟,并且不改变其他类型的实例,最后得到一个没有嵌套列表的列表。

压缩(列表){ // 如何 ? }

compress(list) 的结果将是:

['awef', new Object(), 'fgte']

它是快速而清晰的解决方案吗?

【问题讨论】:

    标签: list dart fold


    【解决方案1】:

    简洁实用的 FTW

    List compress(Iterable iterable) => concat(flatten(iterable));
    
    Iterable flatten(Iterable iterable) => 
        iterable.expand((e) => e is Iterable ? flatten(e) : [e]);
    
    List concat(Iterable iterable) => iterable.fold([], (list, e) => 
        list..add((e is String && list.isNotEmpty && list.last is String)
            ? list.removeLast() + e : e));
    

    【讨论】:

    • list..add 在做什么?执行add,但返回list?仍然缺少某种函数应用程序运算符,例如 Haskell 和 XQuery 知道它们...List compress => flatten . concat; 真的很可爱。
    • 是的。这是一个方法级联。该表达式的计算结果为列表,因此该函数返回列表,但允许在同一表达式中调用 add。我实际上更喜欢你的答案,即它更清晰。我只是想看看我能得到多短的代码。
    • 甜,我一直对return list 感到厌恶。我绝对更喜欢你的flatten,尽管concat 有点难以阅读。
    • 我不确定,但我认为使用 flatten 和 expand 也是懒惰的评估,至少在顶层。即它返回一个 Iterable 而不是一个列表。函数组合会很酷——不过需要不同的语法,因为采用了点。不幸的是,如果没有适当的尾调用,Dart 就不能真正成为一种函数式语言。然而,听起来 Ecmascript 规范可能很快就会得到适当的尾调用。这意味着更高版本的 Dart 也应该能够进行适当的尾调用。这将使各种功能性恶作剧成为可能。
    • 好吧,there's Haskell。 ;) 但是和 Dart 一起玩一会儿很有趣。顺便说一句,我可以通过稍微缩短名称将concat 分解为两行。
    【解决方案2】:

    这包括两个问题,一个非常标准的问题(展平列表),然后充分连接字符串。

    flatten(Iterable l) => l.fold([], (List list, element) {
      if (element is Iterable)
        list.addAll(flatten(element));
      else
        list.add(element);
      return list;
    });
    
    concat(Iterable l) => l.fold([], (List list, element) {
      if (element is String && !list.isEmpty && list.last is String)
        list.add(list.removeLast() + element);
      else
        list.add(element);
      return list;
    });
    
    void main() {
      var nested = [ 'a', 'w', ['e', ['f', new Object(), 'f'], 'g'], 't', 'e'];
      print(concat(flatten(nested));
    }
    

    更新:

    另一个concat,灵感来自 Greg Lowe(与我的“大”和他的完全一样,但更简洁):

    concat(Iterable list) => list.fold([], (List xs, x) => xs..add(
        x is String && !xs.isEmpty && xs.last is String ? xs.removeLast() + x : x));
    

    你可以随意组合他和我的功能,他们做的事情完全一样。

    【讨论】:

      【解决方案3】:

      如果您有很多字符串,您可能希望使用 StringBuffer 进行连接。 我的猜测是,在大多数情况下,这不是问题。

      List compress(List list) {
        var sb = new StringBuffer();
        List result = [];
        List compressRec(List list) {
          for (var element in list) {
            if (element is String) {
              sb.write(element);
            } else if (element is List) {
                compressRec(list);
            } else {
              if (sb.isNotEmpty()) {
                result.add(sb.toString());
                sb.clear();
              }
              result.add(element);
            }
          }
        }
        compressRec(list)
        if (sb.isNotEmpty()) {
          result.add(sb.toString());
        }
        return result;
      }
      

      【讨论】:

        【解决方案4】:

        这是我的猜测:

        compress(List l, [List p]) => l.fold(p != null ? p : [], (List t, e) {
          if (e is String) {
            if (t.isEmpty || t.last is! String) t.add(e);
            else t.add(t.removeLast() + e);
          } else if (e is List) compress(e, t);
          else t.add(e);
          return t;
        });
        

        【讨论】:

          【解决方案5】:

          我的尝试

          List flatten(List l) {
            List result = [''];
            int cur = 0;
          
            var add = (f) {
              if(f is String) {
                result[cur] += f;
              } else {
                result.add(f);
                result.add('');
                cur += 2;
              }
            };
          
            l.forEach((e) {
              if(e is List) {
                flatten(e).forEach((e) => add(e));
              } else {
                add(e);
              }
            });
            return result;
          }
          

          【讨论】:

            猜你喜欢
            • 2012-12-11
            • 2016-02-08
            • 2019-07-07
            • 2012-05-17
            • 1970-01-01
            • 1970-01-01
            • 2022-11-17
            • 2019-01-09
            相关资源
            最近更新 更多