代码之家  ›  专栏  ›  技术社区  ›  JC.

这更适合于键值存储还是树?

c#
  •  3
  • JC.  · 技术社区  · 15 年前

    我正在试图找出表示某些数据的最佳方法。它基本上遵循形式manufacturer.product.attribute=value。类似:

    acme.*最低价格=100
    acme.producta.minimumPrice=50
    acme.productb.minimumPrice=60
    acme.productc.defaultcolor=蓝色

    因此,所有Acme产品的最低价格都是100,除了产品A和B。我想将这些数据存储在C中,并具有一些函数,其中getValue(“acme.product c.minimumPrice”)返回100,而getValue(“acme.product a.minimumPrice”)返回50。

    我不知道如何最好地表示数据。有没有一种清晰的方法可以用C编码?

    编辑:我可能不太清楚。这是需要存储在文本文件中的配置数据,然后以某种方式解析和存储在内存中,以便可以像我给出的示例一样检索到它。

    4 回复  |  直到 15 年前
        1
  •  2
  •   Daniel Earwicker    15 年前

    按如下方式写入文本文件:

    Acme.*.MinimumPrice = 100
    Acme.ProductA.MinimumPrice = 50
    Acme.ProductB.MinimumPrice = 60
    Acme.ProductC.DefaultColor = Blue
    

    将其解析为路径/值对序列:

    foreach (var pair in File.ReadAllLines(configFileName)
                             .Select(l => l.Split('='))
                             .Select(a => new { Path = a[0], Value = a[1] }))
    {
        // do something with each pair.Path and pair.Value
    }
    

    现在,对你想做的事情有两种可能的解释。弦 Acme.*.MinimumPrice 可能意味着对于没有特定重写的任何查找,例如 Acme.Toadstool.MinimumPrice 我们回来了 100 -即使没有提到 Toadstool 文件中的任何地方。或者它可能意味着它只能返回 一百 如果有其他特别提到 伞菌 在文件中。

    如果是前者,你可以把所有的东西放在一本平面字典里,在查找时间里,不断尝试不同的密钥变体,直到找到匹配的东西。

    如果是后者,则需要为路径结构中实际发生的所有名称构建一个数据结构,以避免返回实际不存在的名称的值。这对我来说似乎更可靠。

    所以按照后一种选择, Acme.*最低价格 真正的意思是“将这个最低价格值添加到任何没有自己特定定义值的产品中”。这意味着您基本上可以在解析时处理这些对以消除所有星号,将其扩展为配置文件的完整版本:

    Acme.ProductA.MinimumPrice = 50
    Acme.ProductB.MinimumPrice = 60
    Acme.ProductC.DefaultColor = Blue
    Acme.ProductC.MinimumPrice = 100
    

    这方面的好处是,您只需要一个平面字典作为最终表示,您可以使用 TryGetValue [] 去查东西。结果可能会大得多,但这完全取决于配置文件的大小。

    能够 将信息存储得最少,但我会从一开始就使用一些简单的东西,并给它一个非常简单的API,以便您以后在需要时可以重新实现它。您可能会发现(取决于应用程序)使查找过程变得更复杂更糟。

        2
  •  0
  •   JaredPar    15 年前

    我不完全确定你在问什么,但听起来你也在说。

    我需要一个函数,它将为每个产品ID返回一个固定值100,除了两种情况:product a和productb

    在这种情况下,您甚至不需要数据结构。一个简单的比较函数就可以了

    int GetValue(string key) { 
      if ( key == "Acme.ProductA.MinimumPrice" ) { return 50; }
      else if (key == "Acme.ProductB.MinimumPrice") { return 60; }
      else { return 100; }
    }
    

    或者你可以问

    我需要一个函数,如果已经定义了,它将返回一个值;如果没有定义,它将返回100

    在这种情况下,我会使用 Dictionary<string,int> . 例如

    class DataBucket {
      private Dictionary<string,int> _priceMap = new Dictionary<string,int>();
      public DataBucket() {
        _priceMap["Acme.ProductA.MinimumPrice"] = 50;
        _priceMap["Acme.ProductB.MinimumPrice"] = 60;
      }   
      public int GetValue(string key) { 
        int price = 0;
        if ( !_priceMap.TryGetValue(key, out price)) {
          price = 100;
        }
        return price;
      }
    }
    
        3
  •  0
  •   Andrew Bezzub    15 年前

    其中一种方法-可以创建嵌套字典: Dictionary<string, Dictionary<string, Dictionary<string, object>>> . 在代码中,您应该将“acme.producta.minimumPrice”按点拆分,并获取或设置与拆分的块对应的字典值。

    另一种方法是使用Linq2XML:您可以创建 XDocument 使用acme作为根节点,产品作为根节点的子节点,以及属性,您实际上可以将它们存储为产品上的属性或子节点。我更喜欢第二种解决方案,但是如果你有成千上万的产品,速度会慢一些。

        4
  •  0
  •   Nexxas    15 年前

    我会用OOP的方法来解决这个问题。你解释它的方式是,你所有的产品都是由对象表示的,这很好。这似乎是多态性的一个很好的应用。

    我希望所有产品都有一个productBase,它具有默认的虚拟属性

    virtual MinimumPrice { get { return 100; } }
    

    然后您的特定产品(如ProductA)将覆盖以下功能:

    override MinimumPrice { get { return 50; } }