考虑这个例子:
List<int> l = [1, 2, 3, 4, 5];
void DoSomethingWith(IEnumerator<int> e) {
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
using(var e = l.GetEnumerator()) {
DoSomethingWith(e);
DoSomethingWith(e);
}
Run Code Online (Sandbox Code Playgroud)
该片段输出:
True
1
True
1
Run Code Online (Sandbox Code Playgroud)
我预计
True
1
True
2
Run Code Online (Sandbox Code Playgroud)
因为我传递了同一个枚举器。
为什么会这样呢?
我有一个从TCollection派生的集合,实现了GetEnumerator,所以我可以在类似的结构中使用它
for lElem in lCollection do
Run Code Online (Sandbox Code Playgroud)
枚举器派生自TObject,与Delphi提供的标准枚举器完全相同,因此没有所有者.
Delphi帮助提到,如果枚举器支持IDisposable,它将被处理掉,但这只适用于.NET.
我想知道的是,枚举器实例如何以及何时以及由谁被释放?
假设我有一个数组
array = [1,2,3]
Run Code Online (Sandbox Code Playgroud)
我需要创建一个以循环方式返回值的枚举器:
array.next #=> 1
array.next #=> 2
array.next #=> 3
array.next #=> 1
array.next #=> 2
...
Run Code Online (Sandbox Code Playgroud)
我相信这是一个很好的解决方案
警告:这没什么实际价值.我只是想知道发生了什么.
我在网上多次来到这条线:
return to_enum __method__ unless block_given?
Run Code Online (Sandbox Code Playgroud)
我想测试它并用它制作一个生成器方法(#1),然后我尝试了它,并提出了一个枚举器(#2).我对此很满意,认为应该这样做 - 尽管后来我想出了一个使用#lazy(#3)的解决方案,我觉得它看起来更优雅.
你能猜出哪个最快吗?令我惊讶的是,#1是最快的,其次是#2和#3!
对我来说,第一个看起来像一个黑客,并有不良行为,如停止,如果你给它一个空块(而不是只是在给出一个块时抛出错误).
我的问题是,最快的方法是什么?为什么#1比#2快,我错过了什么?如果我的解决方案没问题,客观上最好吗?
编辑:更简单的例子,之前是fizzbuzz(http://pastebin.com/kXbbfxBc)
def method
return to_enum __method__ unless block_given?
n = 0
loop do
n += 1
yield n ** 2
end
end
enum = Enumerator.new do |yielder|
n = 0
loop do
n += 1
yielder.yield n ** 2
end
end
lazy = (1..Float::INFINITY).lazy.map do |n|
n ** 2
end
p method.take 50
p enum.take 50
p lazy.first 50
require 'benchmark/ips'
Benchmark.ips do |bm| …Run Code Online (Sandbox Code Playgroud) 当我转到List <>的定义时,我可以看到它具有实现接口IEnumerator<T>IDisposable和IEnumerator 的公共结构Enumerator 。
IEnumerator应该强制执行Reset-除了Current和MoveNext。但是仅实现了Current和MoveNext。怎么可能?
在哪里找到List <>的Reset()?
var list = new List<int>();
list.Add(23);
list.Add(44);
var Enumerator = list.GetEnumerator();
while (Enumerator.MoveNext())
{
Console.WriteLine(Enumerator.Current);
}
Enumerator.
Run Code Online (Sandbox Code Playgroud)
当我在代码中尝试时,没有Reset():
好的-我试图显示屏幕截图,但是他们不允许我这样做。
但是复制上面的代码后,在Enumerator 的Dot运算符(。)之后没有显示Reset-Method 。
有人知道这一点吗?
我看到它称为mscorlib的一部分的IEnumerator的重置。
var list = new List<int>();
list.Add(23);
list.Add(44);
var Enumerator = list.GetEnumerator();
Enumerator.MoveNext();
Enumerator.MoveNext();
Console.WriteLine(Enumerator.Current);
((IEnumerator<int>)Enumerator).Reset();
Enumerator.MoveNext();
Run Code Online (Sandbox Code Playgroud)
但是,由于IEnumerator是接口,因此如何调用代码?
IEnumerator中的Reset()应该只是一个定义,实现应留给使用该接口的任何人。
但是在某种程度上,这里仅通过定义要实现的接口即可提供实际功能。我在任何地方都看不到实际的实现,而那部分我不理解。
使用时
let directoryEnumerator = FileManager().enumerator(at: ...
Run Code Online (Sandbox Code Playgroud)
在 Swift 3 中,我从文件夹中获取所有文件,例如
"file:///Volumes/MacOS/fasttemp/Fotos/"
Run Code Online (Sandbox Code Playgroud)
结果不包括主要路径(此处为“/Volumes/MacOS”)。所以我得到
"file:///fasttemp/Fotos/2005/"
Run Code Online (Sandbox Code Playgroud)
如何获取完整路径(直接从枚举器)或转换它们。我想使用 URL 函数,而不是通过假设进行操作的字符串函数。
我的班级中有一个File,我想each_line使用相同的功能来实现,File#each_line以便可以使用块或不使用块调用它。在没有块的情况下调用时,Enumerator返回an 。
这是我目前的代码:
def each_line(&block)
if block_given?
read_loop(&block)
else
Enumerator.new do |y|
read_loop(&y)
end
end
end
private
def read_loop(&block)
while line = readline
block.yield line
end
end
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更简洁的惯用方式来实现 each_line 而不是询问是否传递了一个块并且在每种情况下做非常相同的事情只是略有不同。
readline是类中的一个公共方法(它做了更多的事情File#readline。
这种问题的模式(最佳实践)是什么 - 修改集合中的元素(值)?
条件:
在C++中,它很简单,很好,我只是通过一个集合迭代并更改了元素.但是在C#中迭代(使用枚举器)是只读操作(就C++而言,只有const_iterator可用).
那么,如何在C#中做到这一点?
例如:具有"1,2,3,4"修饰的序列将其改变为"1,2,8,9"而不是"1,2,3"或"1,2,3,4,5".
a = [4, 3, 2, nil]
a.max_by { |v| v * 2 } => NoMethodError: undefined method `*' for nil:NilClass
Run Code Online (Sandbox Code Playgroud)
如何重载max_by以忽略nil值?
假设我有一个集合@lines,我想迭代它,但我想根据集合的内容来操纵它是如何迭代的,我该怎么做?
即是这样的:
@lines.each_with_index do |line, index|
if (index % 3 = 0)
jump_to index == next_multiple_of_3
end
end
Run Code Online (Sandbox Code Playgroud)
所以看起来像是这样的:
Element | Index
a | 1
b | 2
c | 3
f | 6
g | 7
h | 8
i | 9
l | 12
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
编辑1
请注意,正如我在下面的评论中所解释的那样,我不一定总是希望跳转到特定的倍数.基本上,我想跳转到一些任意索引,该索引由当前迭代中发生的事情决定.
所以第一次走动,它可以跳过3指数上涨,但是下一次跳跃7指数上涨,然后在接下来的5次1跳跃2指数正常,然后指数上涨.
唯一的常数是确定它在原始迭代中如何进展的方式是基于当前迭代块内发生的事情.
enumerator ×10
ruby ×5
c# ×2
iterator ×2
arrays ×1
c#-4.0 ×1
collections ×1
delphi ×1
delphi-2007 ×1
file ×1
ienumerable ×1
ienumerator ×1
list ×1
overloading ×1
path ×1
performance ×1
ruby-1.9.3 ×1
swift ×1