C#非邪恶的快速数组查找?

时间:2011-07-09 21:19:27

标签: c# arrays performance dictionary

我希望有大量的类实例返回相同的相似数据字段,就像在这个示例实现中一样:

foreach (SomeClass sc in SomeClasses)
{
    System.Console.WriteLine(sc.GetData("1st field"));
    System.Console.WriteLine(sc.GetData("Another field"));
    System.Console.WriteLine(sc.GetData("and another"));
}

// ---- inside SomeClass:

Dictionary<string, string> myData;

public string GetData(string field)
{
    return myData[field];
}

我不喜欢的是字符串散列,查找和匹配,必须在示例中一遍又一遍地发生(我假设字典是如何工作的)。我真的想找到一个更好的方法。

来自C世界,我想到为所有字段分配一个唯一的整数键,这样我就可以改成数组查找:

// ---- inside SomeClass:

string[] MyData;

public string GetData(int field_key)
{
    return MyData[field_key];
}

现在,字段查找是有效的,但它在这些“数组是邪恶的”时间感觉不对,并且处理field_key整数很繁琐且容易出错。

我不知道我是否在这里追逐表演幽灵,只是因为我想找到既高效又干净的设计。

建议?

4 个答案:

答案 0 :(得分:4)

为什么不想要字典查询?字典的非常有效的实现将是对数组中的散列的索引查找。因此,底层实现可以归结为第二个示例中的代码。这将使它成为O(1)

使用词典

答案 1 :(得分:2)

如果您的实例具有相同的字段,为什么不使用属性?

foreach (SomeClass sc in SomeClasses)
{
    System.Console.WriteLine(sc.FirstField);
    System.Console.WriteLine(sc.AnotherField);
    System.Console.WriteLine(sc.AndAnother);
}

答案 2 :(得分:2)

因为这些字段在编译时是未知的,而是动态的和用户可配置的,所以我将稍微修改您的示例程序以使用属性数组。然后我提倡类似于你的方法但使用你自己的自定义类(这里称为MyProperty)而不是字符串。性能至少与字符串方法一样好(并且可能稍微好一点),但好处是它为您提供了更大的灵活性:如果您最终决定性能原因需要使用数组或List方法,那么可以轻松地将数组索引嵌入到MyProperty类中。您必须更改GetData的实现,而不是您的调用代码。

public static void Test1() {
  SomeClass[] SomeClasses; //created somehow

  //in real life, this would be determined dynamically
  var properties=new[] {SomeClass.FirstField, SomeClass.AnotherField, SomeClass.AndAnother};

  foreach(var sc in SomeClasses) {
    foreach(var property in properties) {
      Console.WriteLine(sc.GetData(property));
    }
  }
}

public class SomeClass {
  public static readonly MyProperty FirstField=new MyProperty();
  public static readonly MyProperty AnotherField=new MyProperty();
  public static readonly MyProperty AndAnother=new MyProperty();

  private readonly Dictionary<MyProperty, string> myData=new Dictionary<MyProperty, string>();

  public string GetData(MyProperty property) {
    return myData[property];
  }
}

//default implementation of Equals and GetHashCode are fine here
public class MyProperty {}

但是,由于您的目标应用程序实际上是关于收集一组动态和用户可配置的属性getter,您是否真的想要制作一些Func?像下面这样的代码将非常快,它仍然具有你想要的能力,即它允许你制作一个动态的,用户可配置的属性获取器列表。

public static void Test2() {
  SomeClass[] SomeClasses; //created somehow

  //in real life, this would be determined dynamically
  var getters=new[] {SomeClass.FirstField, SomeClass.AnotherField, SomeClass.AndAnother};
  foreach(var sc in SomeClasses) {
    foreach(var getter in getters) {
      System.Console.WriteLine(getter(sc));
    }
  }
}

public class SomeClass {
  public static readonly Func<SomeClass, string> FirstField=sc => sc.field0;
  public static readonly Func<SomeClass, string> AnotherField=sc => sc.field1;
  public static readonly Func<SomeClass, string> AndAnother=sc => sc.field2;

  private string field0;
  private string field1;
  private string field2;
}

答案 3 :(得分:1)

首先,如果您不确定这对您来说是一个性能问题,那么是的,您正在追逐性能重影并且您当前的实现很好。

但如果您在分析期间发现您确实需要更快地制作此代码,那么您似乎没问题。 “阵列是邪恶的”大多数情况下只在公共接口中才有效,将它们用于实现是很好的。

我会对您的代码进行一些更改:创建一个包含字段的enum并使用该字段代替int。它同样快速且可读性更高。如果在编译时不知道字段,则使用int就可以了。如果您在编译时知道某些字段,则可以为它们使用静态属性。