草庐IT

c++ - 根据属性从列表中选择元素

coder 2024-02-05 原文

我正在开发一个旨在渲染大量形状的应用程序。每个形状都可以分配给一个特定的

我将输入数据作为形状列表获取,其中对于每个形状,我都有一个 string 属性,表示该形状所属的图层。

现在,我需要开发一种方法,允许我只选择(绘制)那些属于给定选定图层列表的形状。 在伪代码中:

void draw_if(sorted_list shapes, list<string> selected_layers)
{
   for each shape in shapes
   {
      if (shape.layer in selected_layers)
        shape.draw();
   }
}

关键是我想尽快执行这个操作;因此我需要选择正确的数据结构和合适的算法。

所选层的列表是一个字符串列表(1÷100 个不同的层),但如果出于性能原因需要,它可以转换为其他数据类型。

形状根据它们的 z 顺序排序。

最佳答案

在寻找复杂的数据结构和算法时,基本的侵入式解决方案经常被忽略,但通常是最快的。

假设您别无选择,只能将选择分开,如果您想要一个非常快速的解决方案,请在每一层中存储一个 bool 选择标志(可以是一个位)。当您形成选择时,除了形成列表外,还要设置这些标志。取消选择图层不仅会将其从您的选择中删除,还会将该选择标志设置为 false。

接下来,将那些用于指示所选层的字符串转换为随机访问结构中的索引(例如:std::vector 或什至是一个普通的旧数组,如果大小可以在编译时确定的话),像这样(简化):

struct Layer
{
    string name;

    // Set this to true when the layer is selected, false 
    // when it is deselected. Use atomics if thread safety 
    // is required.
    bool selected;
};

... 并将 shape.layer 转换为图层的索引(或指针/迭代器)。如果您别无选择,只能从图层字符串开始识别形状属于哪个图层,因为您最初获得了字符串输入(例如:来自您正在加载的文件),然后将这些字符串转换为图层索引/指针/迭代器当您从这些字符串输入创建形状时。在此处使用哈希表或至少 std::set/map(初始形状构造上的字符串搜索应为对数或更好)将这些层字符串转换为层索引/指针/迭代器。

如果除了图层选择状态之外还需要图层选择列表,那么可以这样做(伪代码):

void select(Layer layer, LayerList& layer_selection)
{
     if (!layer.selected)
     {
          layer.selected = true;
          layer_selection.insert(&layer);
     }
}

void deselect(Layer layer, LayerList& layer_selection)
{
     if (layer.selected)
     {
          layer.selected = false;
          layer_selection.erase(&layer);
     }
}

... 您的图层选择将索引/指针/迭代器存储到图层的位置。选择和取消选择列表的插入/删除都可以在恒定时间内完成(即使在最坏的情况下),没有散列开销,并且如果您喜欢层选择并使用固定的,则同时保留插入顺序分配器(这是一个涉及 placement new、union 和内存池的复杂主题,所以如果需要我会深入研究它,但为了简洁暂时忽略它)。

现在你的主要伪代码变成了这样的东西:

void draw_if(list shapes, list layers)
{
   for each shape in shapes
   {
      if (layers[shape.layer].selected)
        shape.draw();
   }
}

...或者如果你使用指针/迭代器的话:

void draw_if(list shapes, list layers)
{
   for each shape in shapes
   {
      if (shape.layer->selected)
        shape.draw();
   }
}

就性能而言,很难击败它,因为即使是最优化的哈希表也无法击败对内存的简单索引数组访问,除了哈希之外,您仍然需要访问内存。现在如果你能巩固“选择形状”的思想,通过选择/取消选择图层的过程预先形成选择的形状,那么你可以这样做:

void draw_selected(list selected_shapes)
{
   for each shape in selected_shapes
       shape.draw();
}

... 这可能会更快,前提是形成所选形状列表的额外成本可以通过在必须更改之前重复使用它来补偿。请注意,在这种情况下,您仍然希望将这些字符串转换为索引,因为您不希望您的“选定形状”列表不仅仅是一个简单的数组。形成选定的形状列表:

ShapeList selected_shapes(ShapeList all_shapes, LayerList layers)
{
     // Forming this in advance will help if it is reused for
     // numerous drawing frames before it needs to change (ex:
     // before the Z-order changes, before new elements are inserted
     // or existing ones removed, before the layer selection changes).
     ShapeList results;
     for each shape in all_shapes:
          if layers[shape.layer].selected)
             results.push_back(shape);
     return results;
}

...由于我们现在存储在层中的选择状态,它的形成和访问(由于完美紧凑的形状选择数组的空间局部性)仍然比哈希表更便宜。

这使一切缓存友好,并避免昂贵的(相对而言)数据结构,如哈希表,除了在初始字符串->索引/指针转换部分(您只需要在从字符串输入创建形状时)。在这种情况下,唯一需要进行任何类型的搜索(对数或恒定时间哈希/trie)的地方是当您将从用户输入获得的那些形状层字符串转换为索引/指针/迭代器时。其他一切都是 O(1)(甚至是最坏情况下的复杂度)并且甚至不需要散列。

关于c++ - 根据属性从列表中选择元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30945464/

有关c++ - 根据属性从列表中选择元素的更多相关文章

  1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  5. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  6. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  7. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  8. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  9. ruby - 在哈希的键数组中追加元素 - 2

    查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用

  10. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

随机推荐