2013-11-06 3 views
1

У меня есть массив characters, который я буду перебирать. Как только я нахожу персонажа, которого я раньше не нашел, я что-то делаю.HashSet для уникальных символов

Это означает, что мне нужно отслеживать, какие персонажи я уже встречал. Мой первый выбор был HashSet, но я не уверен, что это правильный выбор, поскольку hashing один символ может занять больше времени, чем просто comparing двух символов. Интересно, правда ли это.

  1. Является ли HashSet правильным выбором для этого, или есть лучшие варианты, которые, например, используют очень маленький хеш или вообще ничего.

Разъяснение свалка

Массив фактически два массива х мерный, которые я получаю от функции, написанной в колледже. Мне также нужно найти положение каждого персонажа. Позиция какого типа определенного типа не имеет значения, если функция не вызывается дважды для типа символа.

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

+3

Что такое обычный 'Set'? –

+0

Я предположил, что в C# есть набор. дайте несколько минут, чтобы понять это. –

+0

Похоже, что нет. Позвольте мне перефразировать мой вопрос. –

ответ

3

Если вас интересует только ASCII, тогда лучшим подходом будет массив размером 128 и литой в int.

boolean[] array = new bolean[128]; 
char c = 'a'; 
array[(int) c] = true; 

Любой вид более крупной кодировки, определенно просто использующий карту, я бы подумал.

+0

Каковы ваши предположения относительно использования карты ('HashSet', я предполагаю), если диапазон символов больше? Сохранение памяти? 'Bool []' достаточно большой для всего 16-разрядного Unicode-набора только 64 КБ. И вы можете сделать это в 8 КБ, если вы используете «BitArray». –

+1

Хорошая реализация HashSet, подобная той, что есть в C#, вероятно, не ударит 64kb в разреженной реализации, и вы сравниваете два линейных подхода, поэтому накладные расходы должны быть тривиальными с разумным количеством обращений. Мой резонанс - это неясно, кто будет лучшим решением, и когда он сомневается в том, что будет легко, профильно и оптимизировано только в случае необходимости. – gbtimmon

+0

По крайней мере, я не думал, что это займет весь 64kb ... может быть, это так ... – gbtimmon

1

Вы можете получить HashSet из массива, как:

char[] array = new[] { 'a', 'a', 'b', 'c', 'c' }; 
HashSet<char> hashSet = new HashSet<char>(array); 

Было бы лучше, чем подход сравнения и выявления дубликатов самостоятельно.

+0

Но OP должен «что-то сделать», если найдет нового персонажа. –

+0

Массив на самом деле представляет собой двумерный массив, который я получаю от функции, написанной колледжем. Мне также нужно найти положение каждого персонажа. Позиция какого типа определенного типа не имеет значения, если функция не вызывается дважды для типа символа. Вот почему я не могу использовать то, что вы предложили. –

+0

@AartStuurman, тогда может быть 'HashSet' не то, что вам нужно, вы можете использовать' Словарь' с индексом, являющимся ключом, и 'char' является значением, я все еще не уверен в ваших требованиях. – Habib

1

Если говорить о простом полукокса я думаю, что вы можете пойти с чем-то же просто, как:

bool[] map = new bool[256]; 

И для доступа к элементу:

map[(int)'a']; 
1

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

var lookup = Enumerable.Repeat(true, 256).ToArray(); 
var otherCharacters = HashSet<char>(); 

, тогда вы можете использовать поиск для «маленькие» персонажи, листать его true, когда нашли, и использовать otherCharacters для юникода вещи ...

Что-то вроде этого:

foreach (var c in myListOfChars) 
{ 
    try 
    { 
     if (!lookup[(int)c]) { // do something } 
     lookup[(int)c] = true; 
    } 
    catch (IndexOutOfRangeException e) 
    { 
     if (!otherCharacters.Contains(c)) { // do something } 
     otherCharacters.Add(c); 
    } 
} 

Это ударит медленный бит для символов за пределами диапазона таблицы поиска, которая в зависимости от вашего языка является приемлемой или нет. Для латинских наборов символов это должно работать нормально!

Теперь ... не весь мир работает в диапазоне ascii/latin-1 ..., проходя через тексты на арабском языке, потребуется другой диапазон.

EDIT: Гм ... Я только что проверил вывод GetHashCode() для чисел ... ну ... получается, что хэш-код для int является сам ИНТ ... так оптимизации с нашими таблица поиска, вероятно, просто глупо ... Я собираюсь проверить реализацию HashSet далее ...

+0

Это может быть хорошим вариантом, так как здесь важна производительность. –

+1

Зачем ограничивать массив 'lookup' до 256 символов? Это не похоже на 128 КБ для полной таблицы - это огромный объем памяти. Кроме того, нет необходимости в проверке 'Contains' в' HashSet'. 'Add' не будет бросаться, если вы попытаетесь добавить элемент, который уже существует. –

+0

@JimMischel, справа, я aggree. Полностью зависит от того, что вы пытаетесь сделать здесь. Тем не менее, я думаю, что этот пример хорош, потому что он показывает технику для оптимизации общего случая с резервными исправлениями для особых случаев ... –

Смежные вопросы