在 Python 3 中的列表上从左到右应用操作 [英] Left to right application of operations on a list in Python 3

查看:31
本文介绍了在 Python 3 中的列表上从左到右应用操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么可能的方法可以在 Python 中实现对列表的非惰性从左到右调用操作吗?

例如斯卡拉:

 val a = ((1 to 50).map(_ * 4).过滤器(_ <= 170).filter(_.toString.length == 2).filter (_ % 20 == 0).zipWithIndex.map{ case(x,n) =>s结果[$n]=$x"}.mkString(" .. "))a: 字符串 = 结果[0]=20 .. 结果[1]=40 .. 结果[2]=60 .. 结果[3]=80

虽然我意识到很多人不会喜欢上面的语法,但我喜欢从左到右移动并随时添加任意操作的能力.

当有三个或更多操作时,Python for 理解是 IMO 不容易阅读的.结果似乎是我们需要把所有东西都分成几块.

[f(a) for a in g(b) for b in h(c) for ..]

提到的方法有机会吗?

注意:我尝试了一些库,包括 toolz.functoolz.Python 3 惰性求值使这个问题变得复杂:每个级别返回一个 map 对象.此外,它是否可以对输入 list 进行操作并不明显.

解决方案

@JohanL 的回答很好地了解了标准 Python 库中最接近的等价物是什么.

我最终在 2019 年 11 月改编了 Matt Hagy 的一个要点,现在在 pypi

在对可用的第三方库进行相当彻底的审查后,Pipe https://github.com/JulienPalard/Pipe 最适合需求.

您可以创建自己的管道函数.我把它用于处理下面显示的一些文本.粗体线是工作发生的地方.所有那些 @Pipe 的东西我只需要编码一次就可以重复使用.

这里的任务是关联第一个文本中的缩写:

rawLabels="""Country: 国家名称Agr:农业就业百分比Min:采矿业就业的百分比男性:制造业就业百分比PS:电源行业从业人员比例骗局:建筑业就业百分比SI:服务业就业百分比Fin:从事金融业的百分比SPS:从事社会和个人服务的百分比TC:在运输和通信""中使用的百分比

在第二个文本中带有关联标签:

mylabs = 乡村农业矿业制造电力建设服务金融社会运输"

这是功能操作的一次性编码(在后续管道中重用):

@Pipedef split(iterable, delim=' '):for s in iterable: yield s.split(delim)@管道定义修剪(可迭代):for s in iterable: yield s.strip()@管道def pzip(iterable,coll):for s in zip(list(iterable),coll): yield s@管道def 切片(可迭代,变暗):如果 len(dim)==1:对于可迭代中的 x:产量 x[dim[0]]elif len(dim)==2:对于可迭代中的 x:对于 x[dim[0]] 中的 y:产量 y[dim[1]]@管道def toMap(可迭代):返回字典(列表(可迭代))

这是最重要的结局:全部在一个管道中:

labels = (rawLabels.split('
')|修剪|分裂(':')|切片([0])|pzip(mylabs.split(' '))|映射 )

结果:

print('labels=%s' % repr(labels))标签={'PS':'电源','最小':'采矿','国家':'国家','SPS':'社会','TC':'运输','SI':'服务', 'Con': 'Construction', 'Fin': 'Finance', 'Agr': '农业', 'Man': '制造业'}

Is there any possible way to achieve a non-lazy left to right invocation of operations on a list in Python?

E.g. Scala:

 val a = ((1 to 50)
  .map(_ * 4)
  .filter( _ <= 170)
  .filter(_.toString.length == 2)
  .filter (_ % 20 == 0)
  .zipWithIndex
  .map{ case(x,n) => s"Result[$n]=$x"}
  .mkString("  .. "))

  a: String = Result[0]=20  .. Result[1]=40  .. Result[2]=60  .. Result[3]=80

While I realize many folks will not prefer the above syntax, I like the ability to move left to right and add arbitrary operations as we go.

The Python for comprehension is IMO not easy to read when there are three or more operations. The result seems to be we're required to break everything up into chunks.

[f(a) for a in g(b) for b in h(c) for ..]

Is there any chance for the approach mentioned?

Note: I tried out a few libraries including toolz.functoolz. That one is complicated by Python 3 lazy evaluation: each level returns a map object. In addition, it is not apparent that it can operate on an input list.

解决方案

The answer from @JohanL does a nice job of seeing what the closest equivalent is in standard python libraries.

I ended up adapting a gist from Matt Hagy in November 2019 that is now in pypi

https://pypi.org/project/infixpy/

from infixpy import *
a = (Seq(range(1,51))
     .map(lambda x: x * 4)
     .filter(lambda x: x <= 170)
     .filter(lambda x: len(str(x)) == 2)
     .filter( lambda x: x % 20 ==0)
     .enumerate() 
     .map(lambda x: 'Result[%d]=%s' %(x[0],x[1]))
     .mkstring(' .. '))
print(a)

  # Result[0]=20  .. Result[1]=40  .. Result[2]=60  .. Result[3]=80

Other approaches described in other answers

Older approaches

I found a more appealing toolkit in Fall 2018

https://github.com/dwt/fluent

After a fairly thorough review of the available third party libraries it seems the Pipe https://github.com/JulienPalard/Pipe best suits the needs .

You can create your own pipeline functions. I put it to work for wrangling some text shown below. the bolded line is where the work happens. All those @Pipe stuff I only have to code once and then can re-use.

The task here is to associate the abbreviation in the first text:

rawLabels="""Country: Name of country
Agr: Percentage employed in agriculture
Min: Percentage employed in mining
Man: Percentage employed in manufacturing
PS: Percentage employed in power supply industries
Con: Percentage employed in construction
SI: Percentage employed in service industries
Fin: Percentage employed in finance
SPS: Percentage employed in social and personal services
TC: Percentage employed in transport and communications"""

With an associated tag in this second text:

mylabs = "Country Agriculture Mining Manufacturing Power Construction Service Finance Social Transport"

Here's the one-time coding for the functional operations (reuse in subsequent pipelines):

@Pipe
def split(iterable, delim= ' '):
    for s in iterable: yield s.split(delim)

@Pipe
def trim(iterable):
    for s in iterable: yield s.strip()

@Pipe
def pzip(iterable,coll):
    for s in zip(list(iterable),coll): yield s

@Pipe
def slice(iterable, dim):
  if len(dim)==1:
    for x in iterable:
      yield x[dim[0]]
  elif len(dim)==2:
    for x in iterable:
      for y in x[dim[0]]:
        yield y[dim[1]]
    
@Pipe
def toMap(iterable):
  return dict(list(iterable))

And here's the big finale : all in one pipeline:

labels = (rawLabels.split('
') 
     | trim 
     | split(':')
     | slice([0])
     | pzip(mylabs.split(' '))
     | toMap )

And the result:

print('labels=%s' % repr(labels))

labels={'PS': 'Power', 'Min': 'Mining', 'Country': 'Country', 'SPS': 'Social', 'TC': 'Transport', 'SI': 'Service', 'Con': 'Construction', 'Fin': 'Finance', 'Agr': 'Agriculture', 'Man': 'Manufacturing'}

这篇关于在 Python 3 中的列表上从左到右应用操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆