gpt4 book ai didi

c# - 快速将多个对象映射到另一个对象的数据结构

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:23:37 25 4
gpt4 key购买 nike

我的申请需要一个不同的数据结构。
实际上,我有一个由“节点”组成的自定义数据结构。
我的任务如下:
给定多个不同的节点(其中获取的节点数未知)检索或创建一个新节点。它让我想起了一个包含多个参数的函数的缓存。唯一的区别是,所有参数和返回值都具有相同的类型,我返回的值可能稍后作为输入提供给我。
例1:
一开始我得到节点a和c,现在我必须创建一个新节点(命名为ac)并返回它。
当我在将来再次获得节点a和c时,我需要能够非常快速地确定我是否已经创建了ac节点并返回它,或者,如果它以前没有创建过,则创建它并返回它。
例2:
当我得到节点c和a时,我必须返回/创建一个不同的节点!我不能返回ac,它必须是一个新节点(ca)。秩序很重要!
在稍后的处理过程中,我也有可能得到我先前创建的节点。
例如,在对我的数据结构的第三次调用中,我完全有可能接收到节点“a和ac”。再次,我必须创建一个新的节点“a-ac”,缓存并返回它。
起初我使用了很多Dictionary<Tuple<Node, Node>, Node>,但这有多个问题:
-创建和比较元组对我的应用程序来说太慢了
-参数的数目是固定的,我需要多个字典,每个字典都有不同的键(2元组,3元组,…)
我也有很多节点。我已经过滤了一些传入的数据,但我将不得不处理至少1500万到2000万个不同的节点。
一本字典似乎不会削减它,性能和内存消耗似乎太高。
我可以自由地修改节点是如何实现的,所以也许我可以使用另一个技巧将多个节点直接链接到另一个节点?
我怎样才能尽可能有效地解决这个问题?
这个问题通常使用什么样的数据结构?

最佳答案

看起来你有很多限制(时间、效率、内存占用)。老实说,我不知道你把这些限制放在哪里。
我曾经创建了一个小的数据结构,它实现了与您想要的类似的功能我想。

public class StackBlock
{
public string Component { get; set; }
public MyObject ResultingObject { get; set; }
public List<StackBlock> Blocks { get; set; }
}

其思想是使用这些来构造一个树,该树用作已创建对象的缓存。对这些特性的一个小描述:
组件是存储 "A""C"值的位置
ResultingObject是您的缓存项 "AC"
块是用来创建块链的。
因此,如果您想存储 "AC"对象,这将是您保存它的结构:
StackBlock
Component: "A"
ResultingObject: null
Blocks: [
StackBlock
Component: "C"
ResultingObject: MyObject "AC"
Blocks: [ ... ]
]

编辑非常简单,项目“cga”将在:
StackBlock "C" -> StackBlock "G" -> StackBlock "A" -> ResultingItem

你可以把积木堆在一起,使组合越来越长。但是,当需要检索对象时,您只需按照以下顺序遍历树:
找到StackBlock A。
在stackblock a中,找到子stackblock c。
在子stackblock c中,查看resultingobject。如果不为空,则返回缓存对象。
请注意,对于每个步骤,如果找不到要查找的内容,则表示尚未创建该对象,因此必须创建该对象,然后将其存储在树中。下次你要求的时候,它现在就可以用了。
在您的例子中,“AC”和“CA”是不同的对象,树允许您将它们存储在不同的位置。
这也将确保在对象已经在内存中时不会创建该对象,因为树结构只允许在单个位置放置特定元素。
我希望这是你想要的方向?
注:这是我的一个很老的项目,在引入linq之前。当使用linq遍历树时,我只能想象得到的代码相当优雅和简洁。我不会让你知道我以前是怎么做的。
对以下评论的答复
如果你有项目“GA”和项目“CGA”,它们将不属于同一个堆栈块“A”。
如果已经缓存了这两个对象,则树将如下所示:
StackBlock C
-> StackBlock G
-> StackBlock A
-> ResultingObject CGA
StackBlock G
-> StackBlock A
-> ResultingObject GA

注意:您将把上面的元素存储在一个列表中。从该列表中,找到第一个元素并开始向下钻取。
我想指出一个可能的混淆点:你看到两个stackblocks“g”和两个stackblocks“a”。这些不是同一个对象。你在我所有的例子中看到的每一个stackblock都是不同的对象(恰好有相同的字母)。
如果您将stackblock定义为一个结构而不是一个类,那么最好理解它。它的工作原理是一样的,并且你不能在你构建的树的不同层上重用同一个StackBlock。
因此,resultingobject不应该是一个列表,因为应该只有一个单独的对象,我们称之为“cga”。整个练习的目的是防止创建重复的对象,因此此数据结构专门为只允许一个位置放置缓存对象而定制。
如果我把这个例子具体化,也许会有帮助,这样你就可以看到所有事情的结局:
StackBlock C
-> StackBlock G
-> ResultingObject CG
-> StackBlock A
-> ResultingObject CGA
-> StackBlock B
-> ResultingObject CGB

StackBlock G
-> ResultingObject G
-> StackBlock A
-> ResultingObject GA
-> StackBlock X
-> ResultingObject GAX
-> StackBlock K
-> ResultingObject GAXK

看这两个叫做“G”的堆叠块。其中一个在顶层,所以它的ResultingObject是简单的G,而另一个是二级StackBlock因此,它的resultingobject是cg,因为您必须解释您向下钻取的整个链。
我希望这有助于澄清这是一个简单的概念,一旦你理解了,但我有一些困难来描述为什么这样做:)

关于c# - 快速将多个对象映射到另一个对象的数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24283945/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com