【问题标题】:How does the Iterable.expand(Iterable Function(dynamic) f) function works in Dart?Iterable.expand(Iterable Function(dynamic) f) 函数在 Dart 中是如何工作的?
【发布时间】:2021-09-25 18:20:15
【问题描述】:

根据documentation 中的示例:

var pairs = [[1, 2], [3, 4]];
var flattened = pairs.expand((pair) => pair).toList();
print(flattened); // => [1, 2, 3, 4];

var input = [1, 2, 3];
var duplicated = input.expand((i) => [i, i]).toList();
print(duplicated); // => [1, 1, 2, 2, 3, 3]

如果它包含嵌套的可迭代对象,它看起来像是将可迭代对象展平,但问题是什么。

【问题讨论】:

  • "问题如何" ...这个问题不是很清楚。你想知道它的具体实现(即你想看它的代码),你想知道它的行为的具体细节(即它是否扁平化嵌套任意数量的迭代),或者你想知道你可能如何实现类似的东西?
  • @jamesdlin 是的,我想知道它在幕后是如何运作的。

标签: function dart iterable


【解决方案1】:

它的基本作用是,它在每次迭代时迭代调用参数函数的可迭代对象,并在迭代结束后连接参数函数返回的可迭代对象,最后返回作为可迭代对象的串联结果。

这是关于它如何工作的总结,让我们使用文档本身的示例来理解它:

var pairs = [[1, 2], [3, 4]];
var flattened = pairs.expand((pair) => pair).toList();
print(flattened); // => [1, 2, 3, 4];

这里我们有一个可迭代的pairs,我们在上面调用了expand() 方法。现在expand() 方法将遍历pairs,每次迭代调用一次参数函数(pair) => pair

注意expand() 方法的语法类似于Iterable<T> expand<T>(Iterable<T> f(T element)),它清楚地表明它接受一个函数作为参数,该函数接受T 类型的参数并返回一个可迭代对象。例如(pair) => pair 其中pair 的类型为List<int>

到目前为止,我们很清楚 expand() 方法在每次迭代时迭代调用参数函数的可迭代对象。参数函数接受一个与可迭代对象类型相同的参数,并返回一个可迭代对象。

最后,expand() 方法连接参数函数返回的迭代,一旦迭代迭代,例如pairs 结束 [1, 2] + [3, 4] = [1, 2, 3, 4]。然后它返回连接的结果,它是一个可迭代的[1, 2, 3, 4]

【讨论】:

    【解决方案2】:

    它基本上只是一个循环中的一个循环,它遍历每个可迭代对象,找到内部可迭代对象的每个内部元素,然后将其作为单个展开的可迭代对象返回。

    我找不到expand 的源代码,但是在我的darq 包中,您可以使用selectMany 方法看到相同的概念(这是因为selectMany 只是expand 与传递给选择器的附加索引)。至于 Dart 的 expand 是如何工作的,请忽略所有处理 index 的部分。

    extension SelectManyExtension<T> on Iterable<T> {
      /// Maps elements in an iterable to collections and then flattens those
      /// collections into a single iterable.
      ///
      /// During iteration, the [selector] function is provided each value in the iterable
      /// along with the index of the value in the iteration. The
      /// returned collection of that function is then iterated over, and each
      /// value in that iteration is provided as the next element of the
      /// resulting iterable. The result is all of the collections flattened so that
      /// their values become elements in a single iterable.
      ///
      /// Example:
      ///
      ///     void main() {
      ///       final list = ['abc', 'de', 'f', 'ghij'];
      ///       final result = list.selectMany((s, i) => s.iterable);
      ///
      ///       // Result: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
      ///     }
      Iterable<TResult> selectMany<TResult>(
          Iterable<TResult> Function(T element, int index) selector) sync* {
        var index = 0;
        for (var v in this) {
          yield* selector(v, index++);
        }
      }
    }
    
    var list = [[1, 2, 3], [4, 5], [6]];
    var flattened = list.selectMany((inner, idx) => inner);
    
    // flattened = [1, 2, 3, 4, 5, 6]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-11
      • 2022-01-16
      • 1970-01-01
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多