#c#
#c#
Вопрос:
Я создал следующее, чтобы предоставить некоторые данные в виде строки соответствия регулярному выражению, а также StringDictionary. Похоже, я мог бы сделать это, используя LINQ с меньшим количеством строк.
private const string STREETTYPES = @"ALY|Alley|AVE|Avenue|BLVD|Boulevard|CIR|Circle|CT|Court|CTR|Center|DR|Drive|EXPY|Expressway|FWY|Freeway|HALL|Hall|HWY|Highway|JCT|Junction|LN|Lane|LP|Loop|PIKE|Pike|PKWY|Parkway|PL|Place|RD|Road|ST|Street|TER|Terrace|TPKE|Turnpike|TRL|Trail|WAY|Way";
private static StringDictionary streetTypes = null;
public static StringDictionary StreetTypes
{
get
{
if (streetTypes != null) return streetTypes;
streetTypes = new StringDictionary();
var streetArray = STREETTYPES.Split(PIPE);
for (int i = 0; i < streetArray.Length-1; i = i 2)
{
streetTypes.Add(streetArray[i], streetArray[i 1]);
}
return streetTypes;
}
}
Комментарии:
1. является ли строка на самом деле константой в реализации? Я думаю, что инициализатор коллекции для словаря был бы довольно аккуратным…
2. Согласен. Определенно лучший вариант.
Ответ №1:
Как насчет просто:
private static readonly StringDictionary streetTypes = new StringDictionary
{
{"ALY","Alley"},{"AVE","Avenue"},{"ALY","Alley"},{"BLVD","Boulevard"},{"CIR","Circle"},
{"CT","Court"},{"CTR","Center"},{"DR","Drive"},{"EXPY","Expressway"},{"FWY","Freeway"},
{"HALL","Hall"},{"HWY","Highway"},{"JCT","Junction"},{"LN","Lane"},{"LP","Loop"},
...
};
Ответ №2:
Вы можете использовать Linq, если вам нужно пересчитать, но если словарь статичен, просто используйте инициализатор:
var input = STREETTYPES.Split('|');
var dict = input.Select( (x,i) => new { Item = x, Index = i })
.Where(x => x.Index % 2 == 0)
.ToDictionary( x=> input[x.Index], x => input[x.Index 1]);
Комментарии:
1. Это не создает StringDictionary.
2. @neontapir: Согласен — возможно, хотя, если OP хочет использовать Linq, он должен использовать a
Dictionary<string,string>
в любом случае
Ответ №3:
Это хорошо?
var x = STREETTYPES.Split(new[] {'|'});
var output = Enumerable
.Range(0, x.Length / 2)
.ToDictionary(s => x[2 * s], s => x[2 * s 1]);
Возможно, можно было бы ее еще больше сжать, но сегодня я наполовину сплю.
Комментарии:
1. Это сработало бы, если бы диапазон содержал
x.Length / 2
элементы и выбранные индексы2*x
и2*x 1
.2. Что он и делает (удобно). Если этого не произойдет, он, вероятно, должен сначала с треском умереть с утверждением.
3. Это не сработает, это создаст n-1 элементов ({0,1}, {1,2}, {2,3} …), и то, чего хочет ОП, — это n/2 ({0,1}, {2,3}, {4,5}…).
4. Теперь это имеет смысл — быстро исправит код. Сказал, что я наполовину спал 🙂
5. Исправлено! Спасибо за предупреждение, все оценили. Обычно модульный тест обнаружил бы это (плохое оправдание ;-))
Ответ №4:
Это даст вам StringDictionary
то, что вы ищете, не выполняя позиционную математику. Если вы можете использовать a Dictionary
, я бы выбрал его и одно из других опубликованных решений.
var types = new StringDictionary();
using (IEnumerator<string> enumerator = streetTypes.Split('|').AsEnumerable().GetEnumerator())
{
while(enumerator.MoveNext())
{
string first = enumerator.Current;
if (!enumerator.MoveNext())
break;
types.Add(first, enumerator.Current);
}
}
Ответ №5:
Бесстыдно срывая конструктор Python dict:
IDictionary<TKey, TVal>
ToDictionary<TKey, TVal>(IEnumerable<TKey> keys,
IEnumerable<TVal> values)
{
return keys.Zip(values, (k, v)=>new {K=k, V=v}).ToDictionary(kv=>kv.K, kv=>kv.V);
}
var str = @"ALY|Alley|AVE|Avenue|BLVD|Boulevard|CIR|Circle|CT|Court|CTR|Center|DR|Drive|EXPY|Expressway|FWY|Freeway|HALL|Hall|HWY|Highway|JCT|Junction|LN|Lane|LP|Loop|PIKE|Pike|PKWY|Parkway|PL|Place|RD|Road|ST|Street|TER|Terrace|TPKE|Turnpike|TRL|Trail|WAY|Way";
var words = str.Split('|');
var keys = words.Where((w, i) => i%2 == 0);
var values = words.Where((w, i) => i%2 != 0);
var dict = ToDictionary(keys, values);
Это приведет к a Dictionary<string, string>
, а не a StringDictionary
. У последнего нет конструкторов копирования, поэтому его нельзя создать с помощью oneliner .
(Теперь я хочу, чтобы в C # было меньше элементарной поддержки специальных структур данных, я скучаю по деструктурирующим назначениям.)
Альтернативная версия, которая не требует Zip() и, таким образом, будет работать в более старых версиях .NET и позволяет избежать выделения списка временных пар ключ / значение:
IDictionary<TKey, TVal>
ToDictionary<TKey, TVal>(IEnumerable<TKey> keys,
IEnumerable<TVal> values)
{
return Enumerable.Range(0, keys.Count()).ToDictionary(i=>keys.ElementAt(i), i=>values.ElementAt(i));
}