在查看Microsoft的各种C#LINQ方法的实现时,我注意到公共扩展方法仅仅是包装器,它以单独的迭代器函数的形式返回实际的实现.
例如(来自System.Linq.Enumerable.cs):
public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ConcatIterator<TSource>(first, second);
}
static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second) {
foreach (TSource element in first) yield return element;
foreach (TSource element in second) yield return element;
}
Run Code Online (Sandbox Code Playgroud)
包装迭代器的原因是什么,而不是将它们合并为一个并直接返回迭代器?
像这样:
public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
foreach (TSource element in first) yield …Run Code Online (Sandbox Code Playgroud) 在Rust中,如何避免编写这些循环?代码采用向量并将三个相邻元素相乘到产品.因此,外部循环遍历可以形成一组三个的所有元素,并且内部循环执行乘法.
我认为,困难在于外循环的不完整迭代(从元素0到last - 3).此外,内环必须使用子范围.
有没有办法避免编写循环?
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let mut products = Vec::new();
for seq in 0..v.len() - 3 {
let mut product = 1;
for offset in 0..3 {
product *= v[seq + offset];
}
products.push(product);
}
Run Code Online (Sandbox Code Playgroud) 我正在迭代两个集合并检查两个集合是否包含相同的元素.我不能使用Java 8.
编辑1年后:
我在问题中创建了方法,以检查两个集合是否包含相同的元素,而不考虑我将两个Collection实现传递给方法的事实.
但Collection不确定元素的排序方式.我正在迭代收藏品.因此,Collection的某些实现可以以随机顺序保存元素,同时包含相同的元素.
如果所有元素都返回0 ,则两个集合都包含可比较的元素,并且内容定义为相等.x.compareTo(y)
如果其中一个为空,则将两个值定义为不同,而不是另一个.我想找到一种优雅的方法来比较nullity并防止对final进行null检查compareTo().
我目前的实施:
public static <T extends Comparable<T>> boolean isSame(@Nullable Collection<T> a, @Nullable Collection<T> b) {
if (a == null || b == null) {
return (a == null && b == null);
}
if (a.size() != b.size()) {
return false;
}
Iterator<T> aIt = a.iterator();
Iterator<T> bIt = b.iterator();
while (aIt.hasNext()) {
T aValue = aIt.next();
T bValue = bIt.next(); …Run Code Online (Sandbox Code Playgroud) 好的,所以这是我得到的一个面试问题,当时只进行了平庸的讨论.我想知道最佳解决方案是什么以及如何最好地实施.
您将得到多个分类列表,构建的东西,使我们能够遍历所有这些从最小的名单最大的元素.
例:
{ -2, 5, 10}
{ 2, 9, 11}
{ -5, 9}
-> -5, -2, 2, 5, 9, 9, 10, 11
Run Code Online (Sandbox Code Playgroud)
更新:
在SO聊天#c-questions-and-answers和@Nican的帮助下,我得到了这艘船以某种方式飞行.我已经发布了我的工作代码作为答案,以便允许其他解决方案.
我在下面发布的答案仍然很混乱,特别是我没有正确实现==和!=.我仍然需要帮助.
这个问题的理由
在线查找干净且简约的自定义迭代器实现并不常见.我相信这个问题可以作为其他人加强对迭代器和最佳实践的理解的良好起点.
我正在尝试创建自定义迭代.
这是我的代码的简化示例:
class SortedArray {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
return 4;
}
}
const testingIterables = new SortedArray();
for(let item of testingIterables as any) { // i have to cast it as any or it won't compile
console.log(item);
}
Run Code Online (Sandbox Code Playgroud)
此代码将在ES6上正确运行,但使用TypeScript,它将编译而不打印可迭代值.
这是TypeScript中的错误还是我错过了什么?
谢谢
A string_view是:
一个对象,可以引用一个连续的连续序列的类似
char对象,其中序列的第一个元素位于零.典型的实现仅包含两个成员:指向常量
CharT和大小的指针.
这允许对a进行稳健但轻量级的检查string.它非常适合递归函数,否则它们将被强制使用char*s或string::iterators来削减字符串.
我的问题是其他容器呢?为什么只提供这个string?那么其他邻近容器,如vector,map,queue,等?
迭代器有一个skip跳过第一个n元素的方法:
let list = vec![1, 2, 3];
let iterator = list.iter();
let skip_iter = iterator.skip(2); //skip the first 2 elements
Run Code Online (Sandbox Code Playgroud)
我找不到一个方法只跳过n迭代器中的-th元素.我是否需要自己实现某些功能,或者我找不到某个方法?
如果我从处理输入stdin用scanLeft,输出结果永远是我最后输入后面一行:
io.Source.stdin
.getLines
.scanLeft("START:")((accu, line) => accu + " " + line)
.foreach(println(_))
Run Code Online (Sandbox Code Playgroud)
结果(我的手动输入前面有>):
> first
START:
> second
START: first
> third
START: first second
Run Code Online (Sandbox Code Playgroud)
我想要的合理输出是:
> first
START: first
> second
START: first second
> third
START: first second third
Run Code Online (Sandbox Code Playgroud)
如您所见,第一个输入行后面的输出应该已经包含第一个输入行的字符串.
我已经尝试过使用它.scanLeft(...).drop(1).foreach(...),但这会导致以下结果:
> first
> second
START: first
> third
START: first second
Run Code Online (Sandbox Code Playgroud)
如何正确省略纯种子以获得所需结果?
[更新]暂时我很满意安德烈泰金的精彩解决方法.非常感谢你的建议.
但是,当然,如果有任何替代方案scanLeft不会将种子作为第一项发送到下一个迭代链中,我将更喜欢该解决方案.
[UPDATE]
用户jwvh理解我的目标并提供了一个很好的解决方案.为了完善他们的建议,我寻求一种预处理线路的方法,然后再将它们发送到累积回调中.因此,readLine不应该在累积回调中调用该命令,而是在我可以预先设置的不同链链接中调用.
考虑一下这个python代码
it = iter([1, 2, 3, 4, 5])
for x in it:
print x
if x == 3:
break
print '---'
for x in it:
print x
Run Code Online (Sandbox Code Playgroud)
它会打印1 2 3 --- 4 5,因为迭代器会it记住它在循环中的状态.当我在JS中看似相同的事情时,我得到的只是1 2 3 ---.
function* iter(a) {
yield* a;
}
it = iter([1, 2, 3, 4, 5])
for (let x of it) {
console.log(x)
if (x === 3)
break
}
console.log('---')
for (let x of it) {
console.log(x)
}Run Code Online (Sandbox Code Playgroud)
我错过了什么?
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将按顺序迭代1到6.我们可以交替迭代相同的列表,以便在1, 3, 5不更改while循环的情况下进行打印吗?
iterator ×10
c++ ×2
java ×2
rust ×2
c# ×1
collections ×1
ecmascript-6 ×1
iterable ×1
java-7 ×1
javascript ×1
linq ×1
loops ×1
null ×1
scala ×1
skip ×1
stl ×1
string ×1
string-view ×1
typescript ×1
yield ×1