Linq 中 Enumerable.Zip 扩展方法有什么用?
Enumerable.Zip
有什么用Linq 中的扩展方法?
What is the use of Enumerable.Zip
extension method in Linq?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
Enumerable.Zip
有什么用Linq 中的扩展方法?
What is the use of Enumerable.Zip
extension method in Linq?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(9)
Zip 运算符使用指定的选择器函数合并两个序列的相应元素。
输出
The Zip operator merges the corresponding elements of two sequences using a specified selector function.
Ouput
Zip
用于将两个序列合并为一个。例如,如果您有序列并且
您想要将每个序列中相同位置的元素相乘得到的序列,
您可以说它
被称为“zip”,因为您将一个序列视为左侧拉链的一侧,另一个序列作为拉链的右侧,拉链操作员将两侧拉在一起,适当地配对牙齿(序列的元素)。
Zip
is for combining two sequences into one. For example, if you have the sequencesand
and you want the sequence that is the result of multiplying elements in the same position in each sequence to obtain
you could say
It is called "zip" because you think of one sequence as the left-side of a zipper, and the other sequence as the right-side of the zipper, and the zip operator will pull the two sides together pairing off the teeth (the elements of the sequence) appropriately.
它迭代两个序列并将它们的元素一一组合成一个新序列。因此,您获取序列 A 的一个元素,将其与序列 B 中的相应元素进行转换,结果形成序列 C 的一个元素。
一种思考方式是,它与
Select
类似,除了它不是转换单个集合中的项目,而是同时适用于两个集合。来自 有关该方法的 MSDN 文章:
如果您要在命令式代码中执行此操作,那么您' d 可能会做这样的事情:
或者如果 LINQ 中没有
Zip
,您可以这样做:当您将数据分散到简单的、类似数组的列表中(每个列表都有相同的列表)时,这很有用长度和顺序,每个都描述同一组对象的不同属性。
Zip
可帮助您将这些数据片段组合成更连贯的结构。因此,如果您有一个州名称数组和另一个缩写数组,您可以将它们整理到一个 State 类中,如下所示:
It iterates through two sequences and combines their elements, one by one, into a single new sequence. So you take an element of sequence A, transform it with the corresponding element from sequence B, and the result forms an element of sequence C.
One way to think about it is that it's similar to
Select
, except instead of transforming items from a single collection, it works on two collections at once.From the MSDN article on the method:
If you were to do this in imperative code, you'd probably do something like this:
Or if LINQ didn't have
Zip
in it, you could do this:This is useful when you have data spread into simple, array-like lists, each with the same length and order, and each describing a different property of the same set of objects.
Zip
helps you knit those pieces of data together into a more coherent structure.So if you have an array of state names and another array of their abbreviations, you could collate them into a
State
class like so:不要让
Zip
这个名字让您失望。它与压缩文件或文件夹(压缩)中的压缩无关。它实际上得名于衣服上的拉链的工作原理:衣服上的拉链有两侧,每侧都有一串齿。当你朝一个方向走时,拉链会枚举(行进)两侧,并通过咬紧牙齿来关闭拉链。当你朝另一个方向走时,它就会张开牙齿。您可以选择打开或关闭的拉链。这与
Zip
方法的想法相同。考虑一个例子,我们有两个集合。一个保存着字母,另一个保存着以该字母开头的食品名称。为了清楚起见,我将它们称为leftSideOfZipper
和rightSideOfZipper
。这是代码。我们的任务是生成一个集合,其中包含由
:
分隔的水果字母及其名称。就像这样:Zip
来救援。为了跟上我们的拉链术语,我们将此结果称为closeZipper
,左侧拉链的项目我们将称为leftTooth
,右侧拉链的项目我们将称为rightTooth< /code> 原因显而易见:
在上面,我们枚举(遍历)拉链的左侧和拉链的右侧,并对每个齿执行操作。我们正在执行的操作是将左齿(食物字母)与
:
连接起来,然后连接右齿(食物名称)。我们使用以下代码来做到这一点:最终结果是这样的:
最后一个字母 E 发生了什么?
如果您正在枚举(拉动)一条真正的衣服拉链,并且无论左侧还是右侧,一侧的齿数都比另一侧少,会发生什么?那么拉链就会停在那里。
Zip
方法将执行完全相同的操作:一旦到达任一侧的最后一项,它将停止。在我们的例子中,右侧的牙齿较少(食物名称),因此它将停在“甜甜圈”处。DO NOT let the name
Zip
throw you off. It has nothing to do with zipping as in zipping a file or a folder (compressing). It actually gets its name from how a zipper on clothes works: The zipper on clothes has 2 sides and each side has a bunch of teeth. When you go in one direction, the zipper enumerates (travels) both sides and closes the zipper by clenching the teeth. When you go in the other direction it opens the teeth. You either end with an open or closed zipper.It is the same idea with the
Zip
method. Consider an example where we have two collections. One holds letters and the other holds the name of a food item which starts with that letter. For clarity purposes I am calling themleftSideOfZipper
andrightSideOfZipper
. Here is the code.Our task is to produce one collection which has the letter of the fruit separated by a
:
and its name. Like this:Zip
to the rescue. To keep up with our zipper terminology we will call this resultclosedZipper
and the items of the left zipper we will callleftTooth
and the right side we will callrighTooth
for obvious reasons:In the above we are enumerating (travelling) the left side of the zipper and the right side of the zipper and performing an operation on each tooth. The operation we are performing is concatenating the left tooth (food letter) with a
:
and then the right tooth (food name). We do that using this code:The end result is this:
What happened to the last letter E?
If you are enumerating (pulling) a real clothes zipper and one side, does not matter the left side or the right side, has less teeth than the other side, what will happen? Well the zipper will stop there. The
Zip
method will do exactly the same: It will stop once it has reached the last item on either side. In our case the right side has less teeth (food names) so it will stop at "Donut".这里的很多答案都演示了
Zip
,但没有真正解释可以激发Zip
使用的现实生活用例。Zip
是一种特别常见的模式,非常适合迭代连续的事物对。这是通过迭代可枚举的X
自身并跳过 1 个元素来完成的:x.Zip(x.Skip(1))
。视觉示例:这些连续的对对于查找值之间的第一个差异很有用。例如,可以使用连续的
IEnumable
对来产生IEnumerable
。同样,button
的采样bool
值可以解释为NotPressed
/Clicked
/Held 等事件
/已发布
。然后,这些事件可以驱动对委托方法的调用。这是一个例子:打印:
A lot of the answers here demonstrate
Zip
, but without really explaining a real life use-case that would motivate the use ofZip
.One particularly common pattern that
Zip
is fantastic for iterating over successive pairs of things. This is done by iterating an enumerableX
with itself, skipping 1 element:x.Zip(x.Skip(1))
. Visual Example:These successive pairs are useful for finding the first differences between values. For example, successive pairs of
IEnumable<MouseXPosition>
can be used to produceIEnumerable<MouseXDelta>
. Similarly, sampledbool
values of abutton
can be interpretted into events likeNotPressed
/Clicked
/Held
/Released
. Those events can then drive calls to delegate methods. Here's an example:Prints:
我没有代表点可以在评论部分发布,但可以回答相关问题:
您要做的是使用 Array.Resize() 用默认值填充较短的序列,然后将它们 Zip() 在一起。
代码示例:
输出:
请注意,使用 Array.Resize() 有一个警告:Redim Preserve in C#?
如果不知道哪个序列较短,可以创建一个函数来支持它:
普通 .Zip() 和 ZipDefault() 的输出:
返回到原始问题的主要答案,人们可能希望做的另一件有趣的事情(当要“压缩”的序列的长度不同时)是以这样的方式连接它们,以便结束 列表匹配而不是顶部。这可以通过使用 .Skip()“跳过”适当数量的项目来完成。
输出:
I don't have the rep points to post in the comments section, but to answer the related question :
What you would do is to use Array.Resize() to pad-out the shorter sequence with default values, and then Zip() them together.
Code example :
Output:
Please note that using Array.Resize() has a caveat : Redim Preserve in C#?
If it is unknown which sequence will be the shorter one, a function can be created that susses it:
Output of plain .Zip() alongside ZipDefault() :
Going back to the main answer of the original question, another interesting thing that one might wish to do (when the lengths of the sequences to be "zipped" are different) is to join them in such a way so that the end of the list matches instead of the top. This can be accomplished by "skipping" the appropriate number of items using .Skip().
Output:
正如其他人所说,Zip 允许您组合两个集合以在进一步的 Linq 语句或 foreach 循环中使用。
过去需要 for 循环和两个数组的操作现在可以使用匿名对象在 foreach 循环中完成。
我刚刚发现的一个例子,有点愚蠢,但如果并行化有益的话可能会很有用,那就是具有副作用的单行队列遍历:
timeSegments 表示队列中当前或出队的项目(最后一个元素被 Zip 截断) 。
timeSegments.Skip(1) 表示队列中的下一个或查看项目。
Zip 方法将这两者组合成一个具有 Next 和 Current 属性的匿名对象。
然后我们使用Where 进行过滤并使用AsParallel().ForAll 进行更改。
当然,最后一位可能只是一个常规的 foreach 或另一个返回违规时间段的 Select 语句。
As others have stated, Zip lets you combine two collections for use in further Linq statements or a foreach loop.
Operations that used to require a for loop and two arrays can now be done in a foreach loop using an anonymous object.
An example I just discovered, that is kind of silly, but could be useful if parallelization were beneficial would be a single line Queue traversal with side effects:
timeSegments represents the current or dequeued items in a queue (the last element is truncated by Zip).
timeSegments.Skip(1) represents the next or peek items in a queue.
The Zip method combines these two into a single anonymous object with a Next and Current property.
Then we filter with Where and make changes with AsParallel().ForAll.
Of course the last bit could just be a regular foreach or another Select statement that returns the offending time segments.
Zip 方法允许您(调用者)使用合并函数提供程序“合并”两个不相关的序列。 MSDN 上的示例实际上很好地演示了您可以使用 Zip 做什么。在此示例中,您采用两个任意的、不相关的序列,并使用任意函数将它们组合起来(在本例中,只需将两个序列中的项目连接到单个字符串中)。
The Zip method allows you to "merge" two unrelated sequences, using a merging function provider by you, the caller. The example on MSDN is actually pretty good at demonstrating what you can do with Zip. In this example, you take two arbitrary, unrelated sequences, and combine them using an arbitrary function (in this case, just concatenating items from both sequences into a single string).