Какой самый эффективный способ сделать справочную таблицу в C # - PullRequest
5 голосов
/ 06 декабря 2009

Какой самый эффективный способ сделать справочную таблицу в C #

У меня есть справочная таблица. Вроде как

0 "Thing 1"
1 "Thing 2"
2 "Reserved"
3 "Reserved"
4 "Reserved"
5 "Not a Thing"

Так что, если кто-то хочет «Вещь 1» или «Вещь 2», они переходят в 0 или 1. Но они могут также переходить в что-то еще. У меня 256 таких вещей, и, может быть, 200 из них зарезервированы.

Так, что наиболее эффективно, чтобы настроить это?

  • Строковый массив или словарная переменная, которая получает все значения. А затем возьмите целое число и верните значение в этом месте.

Одна проблема, с которой я сталкиваюсь в этом решении, это все «зарезервированные» значения. Я не хочу создавать эти избыточные "зарезервированные" значения. Или же у меня может быть выражение if для всех различных мест, которые «зарезервированы», но теперь они могут быть только 2-3, могут быть 2-3, 40-55 и все разные места в байте. Это если заявление получится неуправляемо быстрым

  • Моим другим вариантом, о котором я думал, было заявление о переключении. И у меня были бы все 50-е известные значения, и я провалился бы по умолчанию для зарезервированных значений.

Мне интересно, если это намного больше, чем создание строкового массива или словаря и просто возвращение соответствующего значения.

  • Что-то еще? Есть ли другой способ рассмотреть?

Ответы [ 9 ]

13 голосов
/ 06 декабря 2009
4 голосов
/ 06 декабря 2009

Абсолютно быстрый способ поиска целочисленных значений в C # - с помощью массива. Это будет предпочтительнее использования словаря, может быть, если вы пытаетесь делать десятки тысяч поисков одновременно. Для большинства целей это излишне; скорее всего вам нужно оптимизировать время разработчика, а не время процессора.

Если зарезервированные ключи - это не просто все ключи, которых нет в таблице поиска (т. Е. Если поиск ключа может вернуть найденное значение, статус не найден или зарезервированный статус), вам потребуется сохранить зарезервированные ключи где-нибудь. Сохранять их как записи словаря с магическими значениями (например, ключ любой записи словаря, значение которой равно null, зарезервировано) можно, если вы не пишете код, который перебирает записи словаря без их фильтрации.

Чтобы решить эту проблему, используйте отдельный HashSet<int> для хранения зарезервированных ключей и, возможно, запекайте все это в классе, например ::

.
public class LookupTable
{
   public readonly Dictionary<int, string> Table { get; }
   public readonly HashSet<int> ReservedKeys { get; }

   public LookupTable()
   {
      Table = new Dictionary<int, string>();
      ReservedKeys = new HashSet<int>();
   }

   public string Lookup(int key)
   {
      return (ReservedKeys.Contains(key))
         ? null
         : Table[key];
   }
}

Вы заметите, что это все еще имеет проблему с магическим значением - Lookup возвращает ноль, если ключ зарезервирован, и выдает исключение, если его нет в таблице, - но, по крайней мере, теперь вы можете перебрать Table.Values без фильтрации магических значений.

3 голосов
/ 06 декабря 2009

Если у вас есть много зарезервированных (в настоящее время неиспользуемых) значений или если диапазон целочисленных значений может стать очень большим, то я бы использовал общий словарь (Dictionary):

var myDictionary = new Dictionary<int, string>();
myDictionary.Add(0, "Value 1");
myDictionary.Add(200, "Another value");
// and so on

В противном случае, если у вас есть фиксированное количество значений и только немногие из них в настоящее время не используются, я бы использовал строковый массив (строка [200]) и установил / оставил зарезервированные записи равными нулю.

var myArray = new string[200];
myArray[0] = "Value 1";
myArray[2] = "Another value";
//myArray[1] is null
2 голосов
/ 06 декабря 2009

Оформить заказ HybridDictionary. Он автоматически настраивает механизм хранения в зависимости от размера, чтобы добиться максимальной эффективности.

http://msdn.microsoft.com/en-us/library/system.collections.specialized.hybriddictionary.aspx

0 голосов
/ 07 декабря 2009

Ваш вопрос подразумевает, что ключ запроса является целым числом. Поскольку у вас не более 256 элементов, ключ запроса находится в диапазоне 0..255, верно? Если это так, просто используйте массив строк из 256 строк и используйте ключ в качестве индекса в массиве.

Если ваш ключ запроса является строковым значением, то это больше похоже на реальную таблицу поиска. Использовать объект Dictionary очень просто, но если вы набираете скорость до 50 или около того фактических ответов, подход «сделай сам», такой как бинарный поиск или trie, может быть быстрее. Если вы используете бинарный поиск, так как количество элементов очень мало, вы можете развернуть его.

Как часто меняется список товаров? Если он изменяется очень редко, вы можете добиться еще большей скорости, генерируя код для поиска, который затем можно скомпилировать и выполнить для выполнения каждого запроса.

С другой стороны, я предполагаю, что вы доказали, что этот поиск является вашим узким местом, либо путем профилирования, либо , получая стеки . Если в этом запросе затрачивается менее 10% времени-времени-медленного, то это узкое место , а не , поэтому вы также можете делать то, что проще всего кодировать.

0 голосов
/ 06 декабря 2009

Я бы использовал словарь для поиска. На сегодняшний день это самый эффективный способ поиска. Использование строки будет выполняться где-то в области O (n), чтобы найти объект.

Может быть полезно иметь второй словарь для всех вас, чтобы сделать обратный поиск, если это необходимо

0 голосов
/ 06 декабря 2009

Загрузить все ваши значения в

var dic = new Dictionary<int, string>();

И использовать это для поиска:

string GetDescription(int val)
{
     if(0 <= val && val < 256)
        if(!dic.Contains(val))
           return "Reserved";
        return dic[val];
    throw new ApplicationException("Value must be between 0 and 255");
}
0 голосов
/ 06 декабря 2009

Я не совсем уверен, что правильно понимаю вашу проблему. У вас есть коллекция строк. Каждая строка связана с индексом. Потребительские запросы дают индекс, и вы возвращаете соответствующую строку, если только индекс зарезервирован . Правильно?

Разве вы не можете просто установить зарезервированные элементы как нулевые в массиве.

Если нет, использование словаря, который не содержит зарезервированных элементов, кажется разумным решением.

В любом случае, вы, вероятно, получите лучшие ответы, если проясните свою проблему.

0 голосов
/ 06 декабря 2009

Встроенный объект Dictionary (предпочтительно общий словарь) идеально подходит для этого и специально предназначен для быстрого / эффективного поиска значений, относящихся к ключам.

Из связанной статьи MSDN:

Получение значения с помощью его ключа очень быстро, близко к O (1), потому что Словарь <(Of <(TKey, TValue>)>) класс реализован в виде хеш-таблицы.

Что касается ваших "зарезервированных" ключей, я бы об этом не беспокоился, если бы мы говорили только о нескольких сотнях ключей / значений. Только когда вы достигнете десятков, а может быть, сотен тысяч «зарезервированных» ключей / значений, вы захотите реализовать что-то более эффективное.

В этих случаях, вероятно, наиболее эффективным контейнером для хранения будет реализация Sparse Matrix .

...