Как преобразовать строку [] в IDictionary? - PullRequest
3 голосов
/ 12 января 2011

Как преобразовать String[] в IDictionary<String, String>?

Значения в индексах 0,2,4, ... должны быть ключами, и, следовательно, значения в индексах 1,3,5, ... должны быть значениями.

Пример:

new[] { "^BI", "connectORCL", "^CR", "connectCR" }

=>

new Dictionary<String, String> {{"^BI", "connectORCL"}, {"^CR", "connectCR"}};

Ответы [ 8 ]

11 голосов
/ 12 января 2011

Я бы порекомендовал старый добрый цикл для ясности. Но если вы настаиваете на запросе LINQ, это должно сработать:

var dictionary = Enumerable.Range(0, array.Length/2)
                           .ToDictionary(i => array[2*i], i => array[2*i+1])
8 голосов
/ 12 января 2011
Dictionary<string,string> ArrayToDict(string[] arr)
{
    if(arr.Length%2!=0)
        throw new ArgumentException("Array doesn't contain an even number of entries");
    Dictionary<string,string> dict=new Dictionary<string,string>();
    for(int i=0;i<arr.Length/2;i++)
    {
      string key=arr[2*i];
      string value=arr[2*i+1];
      dict.Add(key,value);
    }
    return dict;
}
6 голосов
/ 12 января 2011

На самом деле нет простого способа сделать это в LINQ (и даже если бы он был, это, конечно, не будет ясным в отношении намерений).Это легко сделать простым циклом:

// This code assumes you can guarantee your array to always have an even number
// of elements.

var array = new[] { "^BI", "connectORCL", "^CR", "connectCR" };
var dict = new Dictionary<string, string>();

for(int i=0; i < array.Length; i+=2)
{
    dict.Add(array[i], array[i+1]);
}
3 голосов
/ 12 января 2011

Примерно так:

        string[] keyValues = new string[20];
        Dictionary<string, string> dict = new Dictionary<string, string>();
        for (int i = 0; i < keyValues.Length; i+=2)
        {
            dict.Add(keyValues[i], keyValues[i + 1]);
        }

Редактировать: Люди в теге C # чертовски быстры ...

1 голос
/ 30 января 2011

Если у вас есть Rx в качестве зависимости, вы можете сделать:

strings
    .BufferWithCount(2)
    .ToDictionary(
         buffer => buffer.First(), // key selector
         buffer => buffer.Last()); // value selector

BufferWithCount(int count) берет первые count значения из входной последовательности и выдает их в виде списка, затем принимает следующие count значения и так далее. То есть из вашей входной последовательности вы получите пары в виде списков: {"^BI", "connectORCL"}, {"^CR", "connectCR"}, ToDictionary затем берет первый элемент списка в качестве ключа и последний (== секунда для списков из двух элементов) в качестве значения.

Однако, если вы не используете Rx, вы можете использовать эту реализацию BufferWithCount:

static class EnumerableX
{
    public static IEnumerable<IList<T>> BufferWithCount<T>(this IEnumerable<T> source, int count)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        if (count <= 0)
        {
            throw new ArgumentOutOfRangeException("count");
        }

        var buffer = new List<T>();

        foreach (var t in source)
        {
            buffer.Add(t);

            if (buffer.Count == count)
            {
                yield return buffer;
                buffer = new List<T>();
            }
        }

        if (buffer.Count > 0)
        {
            yield return buffer;
        }
    }
}
0 голосов
/ 16 января 2014

Pure Linq

  1. Выбор: исходное значение строки проекта и его индекс.
  2. GroupBy: группировать соседние пары.
  3. Преобразовать каждую группу в словарную запись.

string[] arr = new string[] { "^BI", "connectORCL", "^CR", "connectCR" }; </p> <pre><code>var dictionary = arr.Select((value,i) => new {Value = value,Index = i}) .GroupBy(value => value.Index / 2) .ToDictionary(g => g.FirstOrDefault().Value, g => g.Skip(1).FirstOrDefault().Value);

0 голосов
/ 13 января 2011

К вашему сведению, это то, что я закончил тем, что использовал цикл и реализовал его как метод расширения:

internal static Boolean IsEven(this Int32 @this)
{
    return @this % 2 == 0;
}

internal static IDictionary<String, String> ToDictionary(this String[] @this)
{
    if (!@this.Length.IsEven())
        throw new ArgumentException( "Array doesn't contain an even number of entries" );

    var dictionary = new Dictionary<String, String>();

    for (var i = 0; i < @this.Length; i += 2)
    {
        var key = @this[i];
        var value = @this[i + 1];

        dictionary.Add(key, value);
    }

    return dictionary;
}
0 голосов
/ 12 января 2011

Похоже, другие люди уже опередили меня и / или получили более эффективные ответы, но я выкладываю 2 способа:

Цикл for может быть самым ясным способом в этом случае ...

var words = new[] { "^BI", "connectORCL", "^CR", "connectCR" };

var final = words.Where((w, i) => i % 2 == 0)
                 .Select((w, i) => new[] { w, words[(i * 2) + 1] })
                 .ToDictionary(arr => arr[0], arr => arr[1])
                 ;

final.Dump();

//alternate way using zip

var As = words.Where((w, i) => i % 2 == 0);
var Bs = words.Where((w, i) => i % 2 == 1);

var dictionary = new Dictionary<string, string>(As.Count());

var pairs = As.Zip(Bs, (first, second) => new[] {first, second})
                .ToDictionary(arr => arr[0], arr => arr[1])
                ;

pairs.Dump();
...