在 Scala 中使用什么类型来存储内存中的可变数据表?
每次调用函数时,如果给定参数值集的结果尚未记忆,我想将结果放入内存表中。一列用于存储结果,其他列用于存储参数值。
我如何最好地实现这一点?参数有多种类型,包括一些枚举。
在 C# 中,我通常使用 DataTable。 Scala 中有等效的吗?
Each time a function is called, if it's result for a given set of argument values is not yet memoized I'd like to put the result into an in-memory table. One column is meant to store a result, others to store arguments values.
How do I best implement this? Arguments are of diverse types, including some enums.
In C# I'd generally use DataTable. Is there an equivalent in Scala?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以使用
mutable.Map[TupleN[A1, A2, ..., AN], R]
,或者如果内存是一个问题,则使用 WeakHashMap[1] 。下面的定义(基于 michid 博客 中的记忆代码构建)允许您轻松记忆具有多个参数的函数。例如:定义:
定点组合器 (
Memoize.Y
) 使得记忆递归函数成为可能:[1] WeakHashMap 不能很好地用作缓存。请参阅http://www.codeinstructions.com/2008 /09/weakashmap-is-not-cache-understanding.html 和 这个相关问题。
You could use a
mutable.Map[TupleN[A1, A2, ..., AN], R]
, or if memory is a concern, a WeakHashMap[1]. The definitions below (built on the memoization code from michid's blog) allow you to easily memoize functions with multiple arguments. For example:Definitions:
The fixed-point combinator (
Memoize.Y
) makes it possible to memoize recursive functions:[1] WeakHashMap does not work well as a cache. See http://www.codeinstructions.com/2008/09/weakhashmap-is-not-cache-understanding.html and this related question.
anovstrup 建议的使用可变 Map 的版本与 C# 中的版本基本相同,因此易于使用。
但如果您愿意,也可以使用更实用的风格。它使用不可变的映射,充当一种累加器。使用元组(而不是示例中的 Int)作为键的工作方式与可变情况下完全相同。
当然,这有点复杂,但却是一种有用的技术(请注意,上面的代码旨在清晰,而不是速度)。
The version suggested by anovstrup using a mutable Map is basically the same as in C#, and therefore easy to use.
But if you want you can also use a more functional style as well. It uses immutable maps, which act as a kind of accumalator. Having Tuples (instead of Int in the example) as keys works exactly as in the mutable case.
Of course this is a little bit more complicated, but a useful technique to know (note that the code above aims for clarity, not for speed).
作为这个主题的新手,我无法完全理解给出的任何示例(但无论如何还是要感谢)。谨此,我会针对有人来到这里具有相同级别和相同问题的情况提出我自己的解决方案。我认为我的代码对于任何只拥有 非常非常基础的 Scala 知识<的人来说都是非常清晰的/a>.
工作完美。如果我错过了什么,我将不胜感激。
Being a newbie in this subject, I could fully understand none of the examples given (but would like to thank anyway). Respectfully, I'd present my own solution for the case some one comes here having a same level and same problem. I think my code can be crystal clear for anybody having just the very-very basic Scala knowledge.
Works perfectly. I'd appreciate critique If I've missed something.
当使用可变映射进行记忆时,应记住这会导致典型的并发问题,例如在写入尚未完成时执行获取。然而,线程安全的记忆尝试建议这样做,即使不是没有价值,也没有什么价值。
以下线程安全代码创建一个记忆化的斐波那契函数,启动几个调用该函数的线程(名称从“a”到“d”)。尝试几次代码(在 REPL 中),可以轻松地看到
f(2) set
被打印多次。这意味着线程 A 已经启动了 f(2) 的计算,但线程 B 完全不知道并开始了自己的计算副本。这种无知在缓存的构建阶段非常普遍,因为所有线程都看不到已建立的子解决方案,并且会进入else
子句。When using mutable map for memoization, one shall keep in mind that this would cause typical concurrency problems, e.g. doing a get when a write has not completed yet. However, thread-safe attemp of memoization suggests to do so it's of little value if not none.
The following thread-safe code creates a memoized
fibonacci
function, initiates a couple of threads (named from 'a' through to 'd') that make calls to it. Try the code a couple of times (in REPL), one can easily seef(2) set
gets printed more than once. This means a thread A has initiated the calculation off(2)
but Thread B has totally no idea of it and starts its own copy of calculation. Such ignorance is so pervasive at the constructing phase of the cache, because all threads see no sub solution established and would enter theelse
clause.除了Landei的回答之外,我还想建议在Scala中采用自下而上(非记忆化)的方式进行DP是可能的,其核心思想是使用
foldLeft
(s)。计算斐波那契数的示例
最长递增子序列的示例
In addition to Landei's answer, I also want to suggest the bottom-up (non-memoization) way of doing DP in Scala is possible, and the core idea is to use
foldLeft
(s).Example for computing Fibonacci numbers
Example for longest increasing subsequence