【问题标题】:Iterating over only a subset of elements in set仅迭代集合中元素的子集
【发布时间】:2013-12-18 06:36:15
【问题描述】:

我只想迭代集合中的某些元素,而不必每次都修改集合或创建一个新元素。就上下文而言,这是针对游戏的。

假设我们在屏幕上有一组实体 S = { A, B, C, D }。 每个实体都会以某种方式影响其他实体。因此,A 将影响集合 S 中的所有实体,除了它自己。

由于所有实体共享同一个集合,我不想为所有实体创建一个新集合,因为它只缺少实体本身。更重要的是,我想让某些实体不影响其他某些实体。这些实体将包含在该实体的排除集中(例如:B 的排除集 = { D },因此,B 将影响 { A, C }。

我不想在每次迭代时检查元素是否存在于排除集中,并且在循环之前从公共集中删除每个实体并再次添加它们似乎是错误的。此外,另一件显而易见的事情是让每个实体持有一组东西进行迭代(不包括自身和任何被排除的实体),但看起来又很糟糕,因为大多数实体的集合几乎与公共集合完全相同,当在屏幕上添加和删除实体时,我必须同步所有这些集合。更不用说当屏幕上有 10,000 个实体时,那是很多额外的集合。也许我在这里过度考虑空间/时间成本,但我觉得好像有一种更优雅的方式来处理这个问题。

【问题讨论】:

  • 请记住,您不会复制整个集合。只是参考。这还不算多。
  • 确实如此。我想我只是担心在这种方法下它们都需要同步到“主集”。因此,在向游戏添加元素时,您必须添加到所有集合而不是只添加主集合。我在网上找到了一个 ObservableSet 实现,可以很容易地做到这一点,尽管它在向集合中添加/删除任何元素时会增加少量开销。不过,我很高兴 Contains 的速度快如闪电。

标签: c# set


【解决方案1】:

您希望能够对集合中的所有元素执行一些operation,除了"acting" element 和执行元素exclude-list 中的一些其他元素,对吗?

如果这是正确的,那么您可以将每个元素连同它应该排除的任何其他元素一起包含在它自己的排除列表中,并遍历不在该列表中的所有元素。

简化为伪代码:

var originalSet = { A, B, C, D, E }
var excludeListForA = {A, B, C} // <-- Note that A is in it's own list!

// To update D and E:
var setToActOn = originalSet.Where(element => excludeListForA.Contains(element));

只要您现在只使用引用,您应该能够更改 setToActOn 中的元素以更新 originalSet 中的正确元素。

【讨论】:

  • 这看起来很干净,但我开始担心我不懂 linq。不会 .Where 需要检查 originalSet 中的每个元素排除 excludeList 中的元素,然后我可以对其进行迭代?如果是这样,这将比仅为每个实体保留一个子集(不包含自身和任何排除的实体)并对该集合进行一次快速迭代要慢得多。 (尽管在这种情况下,我必须在添加到 originalSet 时降低速度,需要同步到所有实体上的所有集合)。
  • 虽然,我只能在排除集或主集更改时才使用上面的代码做到这一点......而不是每次迭代......
【解决方案2】:

我不完全确定这就是你所追求的,但是怎么样

var masterSet = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var member = 5;
var exclusions = new List<int> { 4, 6 };

var subSet = masterSet
 .Where(x => !exclusions.Any(y => x) && x == member)
 .ToList(); // or not to list and do stuff with say Select or something

正如 Marcin 已经提到的,这只会对引用起作用。因此,这里的真正开销(据我所知)来自 LINQ 迭代。

当然集合的类型会有所不同,比较子句也可能需要更改。

【讨论】:

  • 虽然这可行,但似乎我们需要在每次迭代时迭代整个 masterSet 以生成子集,即使在只有 1 或 2 个实体的情况下也是如此我们想省略的 1000 个,这似乎太昂贵了。
  • 在这种情况下,我想在加载主集时可以构造某种集/子集矩阵。当然,如果排除集随时间发生变化,我想不出另一种方法来处理这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 2012-05-13
  • 2011-11-14
相关资源
最近更新 更多