微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

优化复杂的列表理解语句

如何解决优化复杂的列表理解语句

如何优化Step 3中的列表理解语句?

背景:

在现实世界中:

  • r 包含大约 500 个元素和
  • a 包含约 100 万个元素

请注意,Step 3ra 上的嵌套循环。因此,这需要很多时间。为简单起见,以下代码中的 ra 被缩短。

我还提到了这个函数 some_heavy_calculation(),用于背景目的。这个函数这里就不展开了,但是由于它也被调用len(r) * len(a)次,所以也消耗了很多时间。

为了加快速度,我注意到通过引入“更快”的替代方案,我可以避免 90-95% 的 some_heavy_calculation() 调用。唯一的问题是 Step 3 现在需要很多时间。事实上,这一步消耗的时间比我能节省的时间还要多。

def some_heavy_calculation(rules,data) -> list:
    # ...
    return []

# r = input rules
r =  ['x','y','z']

# a = input data
a =  [7,7,4,2,8,9,7    ]

#########
# Slow alternative: b = result of some_heavy_calculation(r,a)
# b = expected result,size: [ r x a ]
b = [[True,True,False,True],[True,[False,False]]
#########

#########
# Faster:
# Since these steps avoids 90-95 % of all the calls to some_heavy_calculation()
#
# Step 1: c = a in order,but without duplicates
c =  [7,9                                ] 

# Step 2: d = result of calculation,size: [ r x c ]
d = [[True,False                            ],False                            ]]

# Step 3: e = should equal b
e = [[d[ri][next(ci for ci,cv in enumerate(c) if cv == av)] for ai,av in enumerate(a)] for ri,rv in enumerate(r)]
#########

str(b) == str(e) # <--- returns True

解决方法

在我看来,您需要的是一个名为 memoization 的模式。

有一个 functools.cache 装饰器(对于 Python lru_cache),您可以这样使用:

func tetherAmount(addrHex string) {
    conn,err := ethclient.Dial("https://mainnet.infura.io/v3/[api_here]")
    if err != nil {
        log.Fatal("Whoops something went wrong!",err)
    }

    contract,err := NewTetherToken(common.HexToAddress("0xdAC17F958D2ee523a2206206994597C13D831ec7"),conn)
    if err != nil {
        log.Fatalf("Failed to initiate contract: %v",err)
    }

    amount,_ := contract.BalanceOf(&bind.CallOpts{},common.HexToAddress(addrHex))
    decimals,_ := contract.Decimals(&bind.CallOpts{})

    fmt.Println("amount:",float64(amount.Int64())/math.Pow(float64(10),float64(decimals.Int64())))
}

使用 memoization 可以有效地对每个值进行一次计算(如您所见,节省了 90-95%),而且还以内存高效的方式(无需组合许多大型列表或数组)。

另一个潜在的优化是使用 import functools @functools.cache def some_heavy_calculation_per_item(rules,value) -> bool: # ... return [] def some_heavy_calculation(rules,data) -> list: # ... returned = [] for value in data: returned.append(some_heavy_calculation_per_item(rules,value)) return returned 而不是在 yield 函数中构造列表,但这取决于您使用结果的方式 - 如果逐个值,那么 some_heavy_calculationing 会改进表现。如果您需要完整的列表 - 那么它根本无济于事。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?