让 Javascript 进行列表理解
让 Javascript 执行类似于 Python 列表理解的操作的最简洁方法是什么?
在Python中,如果我有一个名称为我想“拉出”的对象列表,我会这样做...
list_of_names = [x.name for x in list_of_objects]
在javascript中,除了使用for循环构造之外,我真的没有看到更“美丽”的方法来做到这一点。
仅供参考:我正在使用 jQuery;也许它有一些漂亮的功能使这成为可能?
更具体地说,假设我使用像 $('input')
这样的 jQuery 选择器来获取所有 input
元素,我将如何最干净地创建一个每个 input
元素的所有 name
属性的数组,即所有 $('input').attr('name')< /code> 数组中的字符串?
What is the cleanest way to make Javascript do something like Python's list comprehension?
In Python if I have a list of objects whose name's I want to 'pull out' I would do this...
list_of_names = [x.name for x in list_of_objects]
In javascript I don't really see a more 'beautiful' way of doing that other than just using a for loop construct.
FYI: I'm using jQuery; maybe it has some nifty feature that makes this possible?
More specifically, say I use a jQuery selector like $('input')
to get all input
elements, how would I most cleanly create an array of all the name
attributes for each of these input
elements--i.e., all of the $('input').attr('name')
strings in an array?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
列表理解由几个部分组成。
,从 ES5 开始(所以我认为 IE9+、Chrome 和 FF 都支持这一点),您可以使用
map
和filter< /code> 数组上的函数。
您可以使用映射和过滤器来完成此操作:
这几乎是在不设置其他方法或使用其他框架的情况下获得的最好效果。
至于具体问题...
使用 jQuery:
不使用 jQuery:
[].slice.call()
只是将NodeList
转换为Array
。A list comprehension has a few parts to it.
In JavaScript, as of ES5 (so I think that's supported in IE9+, Chrome and FF) you can use the
map
andfilter
functions on an array.You can do this with map and filter:
That's about as good as it's going to get without setting up additional methods or using another framework.
As for the specific question...
With jQuery:
Without jQuery:
[].slice.call()
is just to convert theNodeList
to anArray
.那些对“美丽”Javascript 感兴趣的人可能应该看看 CoffeeScript,这是一种编译为 Javascript 的语言。它本质上存在是因为 Javascript 缺少诸如列表理解之类的东西。
特别是,Coffeescript 的列表理解比 Python 的更加灵活。请参阅此处的列表理解文档。
例如,此代码将生成
input
元素的name
属性数组。然而,一个潜在的缺点是生成的 Javascript 很冗长(恕我直言,令人困惑):
Those interested in "beautiful" Javascript should probably check out CoffeeScript, a language which compiles to Javascript. It essentially exists because Javascript is missing things like list comprehension.
In particular, Coffeescript's list comprehension is even more flexible than Python's. See the list comprehension docs here.
For instance this code would result in an array of
name
attributes ofinput
elements.A potential downside however is the resulting Javascript is verbose (and IMHO confusing):
所以,Python 的列表推导实际上同时做两件事:映射和过滤。例如:
如果您只想要映射部分,如您的示例所示,您可以使用 jQuery 的映射功能。如果您还需要过滤,可以使用 jQuery 的“grep”功能。
So, python's list comprehensions actually do two things at once: mapping and filtering. For example:
If you just want the mapping part, as your example shows, you can use jQuery's map feature. If you also need filtering you can use jQuery's "grep" feature.
在 2020 年执行此操作
MDN | Array.prototype.map()
2012 年的旧答案
是的,我也怀念列表推导式。
这是一个比 @gonchuki 的答案稍微简洁的答案,并将其转换为实际的数组,而不是对象类型。
一个用例是获取所有选中的复选框并将它们加入到 URL 的哈希中,如下所示:
Do this in 2020
MDN | Array.prototype.map()
Old Answer from 2012
Yeah—I miss list comprehensions too.
Here's an answer that's slightly less verbose than @gonchuki's answer and converts it into an actual array, instead of an object type.
A use case of this is taking all checked checkboxes and joining them into the hash of the URL, like so:
一种可重用的方法是创建一个像这样的小 jQuery 插件:
然后你可以像这样使用它:
它不是列表理解,但在 javascript 中不存在。您所能做的就是使用 javascript 和 jquery 来发挥它的作用。
A re-usable way of doing this is to create a tiny jQuery plugin like this:
Then you could use it like this:
It's not list comprehension, but that doesn't exist in javascript. All you can do is use javascript and jquery for what it's good for.
由@yurik添加:请勿使用。提出了数组推导式,但后来被删除。
推导式是 ECMAScript 6 草案的一部分。目前(2014 年 1 月)只有 Mozilla/Firefox 的 JavaScript 实现了它们。
尽管 ECMAScript 6 最近切换到从左到右语法,类似于 C# 和 F#:
http://kangax.github.io/es5-compat-table/es6/#Array_com经理
Added by @yurik: Do not use. Array comprehensions were proposed but later removed.
Array comprehensions are a part of the ECMAScript 6 draft. Currently (January 2014) only Mozilla/Firefox's JavaScript implements them.
Though ECMAScript 6 recently switched to left-to-right syntax, similar to C# and F#:
http://kangax.github.io/es5-compat-table/es6/#Array_comprehensions
有一种单行方法,它涉及在
列表的构造函数。以及一个使用 long 来生成序列的函数。
它的定义如下:
这是一个基于范围的实现,如 Python 的 range(min, max)
此外,列表理解遵循以下形式:
一些测试:
虽然这个解决方案不是最干净的,但它可以完成工作。在生产中我可能会建议不要这样做。
最后,我们可以选择不对我的“生成”方法使用递归,因为它可以更快地完成工作。或者甚至更好地使用许多流行的 Javascript 库中的内置函数。这是一个重载的实现,也可以容纳对象属性
用法:
我知道语法很糟糕!
祝你好运。
There is a one line approach, it involves using a nested closure function in the
constructor of the list. And a function that goes a long with it to generate the sequence.
Its defined below:
This is a range based implementation like Python's range(min, max)
In addition the list comprehension follows this form:
some tests:
While this solution is not the cleanest it gets the job done. And in production i'd probably advise against it.
Lastly one can choose not to use recursion for my "generate" method as it would do the job quicker. Or even better use a built in function from of the many popular Javascript libraries. Here is an overloaded implementation that would also accommodate for object properties
Usage:
The syntax sucks I know!
Best of luck.
这是 Coffeescript 真正大放异彩的例子
等效的 Javascript 是:
This is an example of a place where Coffeescript really shines
The equivalent Javascript would be:
使用 jQuery
.each()
函数,您可以循环遍历每个元素,获取当前元素的索引,并使用该索引,您可以将 name 属性添加到list_of_names
数组...虽然这本质上是一个循环方法,您指定了您不想要的方法,但它是一个令人难以置信的简洁的循环实现,并允许您在特定选择器上运行循环。
希望有帮助:)
Using jQuery
.each()
function, you can loop through each element, get the index of the current element and using that index, you can add the name attribute to thelist_of_names
array...While this is essentially a looping method, which you specified you did not want, it is an incredibly neat implementation of looping and allows you to run the loop on specific selectors.
Hope that helps :)
数组推导式与 Python 的列表推导式非常相似,是为 ECMAScript 6 提出的,但被放弃以支持
Array.map
和Array.filter
。Array
方法的优点之一是,如果本机不支持它们,也可以实现它们; core.js 等库可以执行此操作。请注意,以下示例使用箭头函数,需要 ES6 支持并且不能进行 polyfill。这不应该是一个问题,因为大多数支持其中一项功能的浏览器应该支持所有功能(某些浏览器在不同版本中添加了这些功能,但差距并不大)。 IE 是个例外,仅支持 Array.map(并且仅从 IE 9 开始)。希望 IE 不再需要支持,因为它已经被 Edge 取代了一段时间了。
Array.map
Array.map
采用一个函数来转换每个元素。基本上,该函数对应于 Python 列表推导式中的表达式。非数组
如果处理不提供
map
的集合或迭代(例如 生成器 或 < code>NodeList),可以使用几个不同的功能之一将其转换为数组,例如 扩展语法 或Array.from
。扩展语法
扩展语法仅在特定上下文中受支持,它的工作原理是将元素从可迭代对象扩展到该上下文:
扩展语法也适用于数组(因为它们是可迭代对象),尽管没有必要这样做:
如果您需要将
map
应用于可能是也可能不是数组的可迭代对象,最安全的方法是首先将其展开到列表中。Array.from
Array.from 方法不仅可以将可迭代对象转换为数组,还可以将任何类似数组的对象(即具有 length 属性和整数索引)转换为数组:
与扩展语法一样,
Array.from
可以安全地应用于数组。如果您需要将map
应用于不可迭代的类数组对象以及数组和可迭代对象,那么这是最安全、最通用的方法。Array.filter
Python 列表理解中的
if
子句转换为Array.filter
:如果 Python 示例扩展为包含
if
子句:这将转换为:
JQuery
JQuery 提供了
.map
和jQuery.map
,两者都包含Array.flatMap
和Array.过滤器。根据 jQuery 版本,
jQuery.map
可以应用于数组和类数组对象*,但不能应用于生成器(根据我的测试)。注意.map
与jQuery.map
的不同之处在于它以相反的顺序传递参数(index, item
而不是item, index
)并返回一个 jQuery 对象。*jQuery 文档断言类似数组的对象应首先转换为数组(例如)
jQuery.makeArray
。当我测试它时,将 jQuery.map 直接应用于类似数组的对象是有效的,尽管在某些情况下这可能会导致问题。Array comprehensions, which are very similar to Python's list comprehensions, were proposed for ECMAScript 6 but dropped in favor of
Array.map
andArray.filter
. One advantage of theArray
methods is they can be implemented if not supported natively; libraries such as core.js do this.Note the following examples use arrow functions, which require ES6 support and can't be polyfilled. This shouldn't be an issue, as most browsers that support one of the features used should support all (some browsers added the features at different versions, but there wasn't a large gap). IE is the exception, supporting only
Array.map
(and that only beginning with IE 9). Hopefully, IE won't need to be supported, as it's been replaced by Edge for some time now.Array.map
Array.map
takes a function that will transform each element. Basically, the function corresponds to the expression in a Python list comprehension.Non-Arrays
If dealing with a collection or iterable that doesn't provide
map
(such as a generator or aNodeList
), it can be converted to an array using one of a couple different features, such as spread syntax orArray.from
.Spread Syntax
Spread syntax, which is only supported in specific contexts, works by expanding the elements from an iterable into that context:
Spread syntax will also work with arrays (since they're iterables), though it's not necessary to do so:
If you need to apply
map
to an iterable that may or may not be an array, it's safest to first spread it into a list.Array.from
The
Array.from
method converts not only iterables but anything array-like (i.e. has alength
property and integer indices) to an array:As with spread syntax,
Array.from
is safe to apply to arrays. If you need to applymap
to non-iterable array-like objects as well as arrays and iterables, it's the safest, most general approach.Array.filter
if
clauses in a Python list comprehension translate toArray.filter
:If the Python example were expanded to include an
if
clause as:This would translate to:
JQuery
JQuery provides
.map
andjQuery.map
, both of which incorporate the functionality ofArray.flatMap
andArray.filter
. Depending on the jQuery version,jQuery.map
can be applied to arrays and array-like objects*, though not generators (according to my testing). Note.map
differs fromjQuery.map
in that it passes arguments in the opposite order (index, item
rather thanitem, index
) and returns a jQuery object.*The jQuery documentation asserts that array-like objects should first be converted to an array with (e.g.)
jQuery.makeArray
. ApplyingjQuery.map
directly to array-like objects worked when I tested it, though there may be some cases where this causes issues.使用 Array.map 的一般情况,需要 javascript 1.6(即意味着,适用于除 IE 之外的所有浏览器或,使用像 MooTools 这样的对象增强框架适用于所有浏览器:
如果处理不提供
map
的可迭代对象(例如生成器),spread 语法 可用于首先创建一个数组:Spread语法也适用于数组,因此如果您需要将
map
应用于任何可迭代对象,最安全的做法是首先将其展开到列表中。(请注意,此示例还使用箭头函数,这需要 ES6 支持。大多数浏览器版本都支持,或者都不支持,如果它本身需要支持,尽管 IE 已经被 Edge 取代了一段时间。)
jQuery 特定示例,适用于每个浏览器:
其他答案。使用
.each
是错误的;不是代码本身,而是实现不是最佳的。编辑:还引入了数组推导式在 Javascript 1.7 中,但这完全依赖于语法,并且无法在本身缺乏语法的浏览器上进行模拟。这是您可以在 Javascript 中获得的与您发布的 Python 代码片段最接近的内容。然而,已从语言中删除
generic case using Array.map, requires javascript 1.6 (that means, works on every browser but IE < 9) or with an object augmenting framework like MooTools works on every browser:
If dealing with an iterable that doesn't provide
map
(such as generators), spread syntax can be used to first create an array:Spread syntax will also work with arrays, so if you need to apply
map
to any iterable, it's safest to first spread it into a list.(Note this example also uses an arrow function, which requires ES6 support. Most browser versions support both or neither. IE supports neither, if it itself needs to be supported, though IE has been replaced by Edge for awhile.)
jQuery specific example, works on every browser:
the other answers using
.each
are wrong; not the code itself, but the implementations are sub-optimal.Edit: there's also Array comprehensions introduced in Javascript 1.7, but this is purely dependant on syntax and cannot be emulated on browsers that lack it natively. This is the closest thing you can get in Javascript to the Python snippet you posted. However that got removed from the language