Значения словаря для перечисления из HashSet of Keys - PullRequest
0 голосов
/ 16 марта 2012

Надеюсь, комментарии объясняют вопрос.У меня большой статический словарь (создается с использованием свежих данных о загрузке программы), который часто используется, и я хочу ссылаться на него как можно более эффективно, а не создавать копии данных и использовать память.Имейте хэш-набор, представляющий подмножество этого словаря, который я должен представить как отсортированный список значений.Новый HashSet или изменения в HashSet, затем я создаю новый класс, который оборачивает приведенный ниже код.Есть ли лучший способ сделать это?Я не мог понять, как использовать внешний HashSet в LINQ.

// FTSwordIDs is a hashset and is also used elsewhere - a lot - hashset for lookup speed
// dlFTSword is Dictionary<Int32, string> and is static and sorted by value (on load) 
// dlFTSword can contain over a million entries and is used a lot of places 
// need to refence it rather than build a new list and eat memory
words = new List<string>();
foreach(Int32 id in dlFTSword.Keys)
{
    if (FTSwordIDs.Contains(id)) words.Add(dlFTSword[id]);
}
return words;

Время составляет 12 мс

try
{
    sqlConRO1.Open();
    sqlCMDRO1.CommandText = "SELECT [ID], [word] FROM [FTSwordDef] WITH (NOLOCK); "; // ORDER BY [word]; ";
    SqlDataReader rdr = sqlCMDRO1.ExecuteReader();
    while (rdr.Read())
    {
        dlFTSword.Add(rdr.GetInt32(0), rdr.GetString(1));
    }
    rdr.Close();
    Debug.WriteLine("dlFTSword.Count = " + dlFTSword.Count.ToString());

}
catch (Exception Ex) { throw new Exception("InitializeData Failed " + Ex.Message); }
finally { sqlConRO1.Close(); }

HashSet<Int32> wordIDs = new HashSet<int>() { 1, 100000, 200000, 300000, 400000, 500000, 600000 };
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();

//List<string> words = dlFTSword.Where(pair => wordIDs.Contains(pair.Key))
//         .Select(pair => pair.Value)
//         .OrderBy(x => x)
//         .ToList();
//List<string> words = wordIDs.Where(key => dlFTSword.ContainsKey(key))
//          .Select(key => dlFTSword[key])
//          .OrderBy(value => value)
//          .ToList();
IEnumerable<string> words = wordIDs.Where(key => dlFTSword.ContainsKey(key))
          .Select(key => dlFTSword[key])
          .OrderBy(value => value);
DateTime dtEnd = DateTime.Now;
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Debug.WriteLine(ts.Milliseconds.ToString());

Ответы [ 2 ]

1 голос
/ 16 марта 2012

Звучит так, как вы хотите:

var words = dlFTSword.Where(pair => FTSwordIDs.Contains(pair.Key))
                     .Select(pair => pair.Value)
                     .ToList();

Обратите внимание, что это позволяет избежать поиска каждого ключа после обнаружения его присутствия.На самом деле мы не ищем ничего в словаре.Это также не включает создание каких-либо других наборов, которые Intersect будут.

Это стоит проверить, хотя:

dlFTSword - это словарь, он статический и отсортирован по значению (включенload)

Если это Dictionary<TKey, TValue>, то не отсортировано.Нет такого понятия, как «отсортированный» Dictionary<TKey, TValue>.Вы можете использовать SortedDictionary<,> или SortedList<,>, но оба они отличаются от Dictionary<,>.

РЕДАКТИРОВАТЬ: Если хэш-набор действительно мал, имеет смысл перебрать , что* На 1025 * больше, чем по каждой паре в словаре:

var words = FTSwordIDs.Where(key => dlFTSword.ContainsKey(key))
                      .Select(key => dlFTSword[key])
                      .OrderBy(value => value)
                      .ToList();

Немного уродливо искать, но это будет значительно быстрее.

1 голос
/ 16 марта 2012
var words = dlFTSword.Keys.Where(FTSwordIDs.Contains).Select(x => dlFTSword[x])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...