简短版本:作为无序项目字典实现的多集合的最佳散列算法是什么?
我正在尝试将一个不可变的multiset(这是一个包或其他语言的多重集合:像一个数学集,除了它可以容纳多个元素)作为字典实现.我已经创建了标准库类的子类collections.Counter,类似于这里的建议:Python hashable dicts,它建议像这样的哈希函数:
class FrozenCounter(collections.Counter):
# ...
def __hash__(self):
return hash(tuple(sorted(self.items())))
Run Code Online (Sandbox Code Playgroud)
创建完整的项目元组会占用大量内存(相对于使用生成器而言),并且哈希将在我的应用程序的内存密集型部分中发生.更重要的是,我的字典键(multiset元素)可能不会是可订购的.
我正在考虑使用这个算法:
def __hash__(self):
return functools.reduce(lambda a, b: a ^ b, self.items(), 0)
Run Code Online (Sandbox Code Playgroud)
我想使用按位XOR意味着顺序与散列值无关,与元组的散列不同?我想我可以在我的数据的无序流序列上半实现Python元组散列算法.请参阅https://github.com/jonashaag/cpython/blob/master/Include/tupleobject.h(在页面中搜索"hash"一词) - 但我几乎不知道有足够的C来阅读它.
思考?建议?谢谢.
set(),但事情必须是哈希的.)
@marcin和@senderle都给出了相同的答案:使用hash(frozenset(self.items())).这是有道理的,因为items()"视图"是设置的.@marcin是第一个,但我给@senderle打了一个复选标记,因为对不同解决方案的大O运行时间进行了很好的研究.@marcin还提醒我要包含一个__eq__方法 - 但是继承自的方法dict会很好用.这就是我实现所有内容的方式 - 欢迎基于此代码的进一步意见和建议:
class FrozenCounter(collections.Counter):
# Edit: A previous version of this code included a __slots__ definition.
# But, from the Python documentation: "When …Run Code Online (Sandbox Code Playgroud) 我不确定我是否完全理解下面的小片段(在 Py v3.6.7 上)中发生的事情。如果有人能向我解释我们如何成功地改变列表,即使 Python 抛出了一个错误,那就太好了。
我知道我们可以改变一个列表并更新它,但是错误是什么?就像我的印象是,如果有错误,那么x应该保持不变。
x = ([1, 2], )
x[0] += [3,4] # ------ (1)
Run Code Online (Sandbox Code Playgroud)
第 (1) 行抛出的 Traceback 是
> TypeError: 'tuple' object doesn't support item assignment..
Run Code Online (Sandbox Code Playgroud)
我明白错误意味着什么,但我无法获得它的上下文。
但是现在如果我尝试打印变量的值x,Python 会说它是,
> TypeError: 'tuple' object doesn't support item assignment..
Run Code Online (Sandbox Code Playgroud)
据我所知,异常发生在 Python 允许列表的突变发生之后,然后希望它尝试重新分配它。我认为它吹到了那里,因为元组是不可变的。
有人可以解释一下引擎盖下发生了什么吗?
编辑 - 1 错误来自 ipython 控制台作为图像;
什么是向编译器指示的最简单和最不突兀的方式,无论是通过编译器选项,#defines,typedefs还是模板,每次我说T,我的意思是T const什么?我宁愿不使用外部预处理器.由于我不使用mutable关键字,因此可以接受重新调整以指示可变状态.
编辑:由于这个意图完全是错误的(因为我不在几个小时内澄清),让我解释一下.本质上,我只想知道在编译时可以使用哪些系统来操作类型系统.我不在乎这是否会产生非标准,错误,不可维护,无用的代码.我不打算在生产中使用它.这只是一种好奇心.
到目前为止的潜在(次优)解决方案:
// I presume redefinition of keywords is implementation-defined or illegal.
#define int int const
#define ptr * const
int i(0);
int ptr j(&i);
typedef int const Int;
typedef int const* const Intp;
Int i(0);
Intp j(&i);
template<class T>
struct C { typedef T const type; typedef T const* const ptr; };
C<int>::type i(0);
C<int>::ptr j(&i);
Run Code Online (Sandbox Code Playgroud) c++ functional-programming const immutability language-extension
在我看来,.NET存在极端缺乏安全,不可变的集合类型,特别是BCL,但我还没有看到很多工作在外面完成.有没有人有任何指向(优选)生产质量,快速,不可变的.NET集合库.快速列表类型是必不可少的.我还没准备好切换到F#.
*编辑:注意搜索者,很快就会进入BCL: .NET不可变集合
是否正确无法更改不可变对象的值?
我有两个关于readonly我想要理解的场景:
如果我有一个集合并将其标记为readonly,如下所示.我还能打电话_items.Add吗?
private readonly ICollection<MyItem> _items;
Run Code Online (Sandbox Code Playgroud)并且对于以下变量,如果稍后我调用_metadata.Change哪个将更改Metadata实例中的一个成员变量的内部值.是_metadata仍然不变?
private readonly Metadata _metadata;
Run Code Online (Sandbox Code Playgroud)对于上面的两个变量,我完全理解我不能在初始化器和构造器之外直接为它们分配新值.
假设我在Java中有一个具有不可变数据的类Foo:
class Foo {
final private int x;
public int getX() { return this.x; }
final private OtherStuff otherstuff;
public Foo(int x, OtherStuff otherstuff) {
this.x = x;
this.otherstuff = otherstuff;
}
// lots of other stuff...
}
Run Code Online (Sandbox Code Playgroud)
现在我想添加一个实用程序方法,该方法创建一个具有相同状态但具有新值x的"兄弟"值.我可以称之为setX():
class Foo
{
...
Foo setX(int newX) { return new Foo(newX, this.otherstuff); }
...
}
Run Code Online (Sandbox Code Playgroud)
但是语义与setX()可变bean对象的标准setter约定不同,所以不知怎的,这感觉不对.
这种方法的最佳名称是什么?
我应该把它withX()或者newX()还是其他什么东西?
编辑:在我的情况下的额外优先级:我有脚本客户端(通过JSR-223和我导出的对象模型),可以轻松获取Foo对象.然而,调用构造函数或创建构建器或其他任何东西都很麻烦.因此,我希望提供此方法以方便脚本编写客户端.
是否有任何优雅的方法从数组中删除对象是一个数组的一部分?我一直在使用React和Redux一段时间,但是每次我必须删除或插入数据而不改变状态时会卡住几个小时.
reducer是一个数组,包含具有ID的对象和带有对象的另一个数组,如下所示:
[
{ id:123,
items:[
{ id: abc,
name: albert
},
...
]
},
...
]
Run Code Online (Sandbox Code Playgroud)
我收到两个ID,需要删除带有ID的项目abc.
我一直在探索Room数据库对象映射库,我想到了一些奇怪的东西.
正如这个答案所暗示的那样,实体数据模型不能具有不可变属性.
但我查看了google与kotlin的持久示例,也Room适用于不可变属性.请从示例中检查此数据类.
这种行为可能是什么原因?
如果我们可以创建不可变值(val属性),这可能是一个很好的功能,因为这会限制程序员在创建对象后更改唯一标识符(如id).
Raku 提供了许多不可变的类型,因此在创建后无法修改。直到我最近开始研究这个领域,我的理解是这些类型不是 持久数据结构——也就是说,与 Clojure 或 Haskell 中的核心类型不同,我相信 Raku 的不可变类型没有利用结构共享来允许廉价的副本。我认为该语句my List $new = (|$old-list, 42);从字面上复制了 中的值$old-list,而没有持久数据结构的数据共享功能。
但是,由于以下代码,我对我的理解的描述是过去时:
my Array $a = do {
$_ = [rand xx 10_000_000];
say "Initialized an Array in $((now - ENTER now).round: .001) seconds"; $_}
my List $l = do {
$_ = |(rand xx 10_000_000);
say "Initialized the List in $((now - ENTER now).round: .001) seconds"; $_}
do { $a.push: rand;
say "Pushed the element to …Run Code Online (Sandbox Code Playgroud) immutability ×10
c# ×2
java ×2
python ×2
android ×1
android-room ×1
c++ ×1
const ×1
dictionary ×1
hash ×1
javascript ×1
kotlin ×1
mutation ×1
python-3.2 ×1
python-3.x ×1
raku ×1
rakudo ×1
readonly ×1
redux ×1
sqlite ×1
tuples ×1