tags:

views:

113

answers:

5

I have a list like

List<string> TempList = new List<string> { "[66,X,X]", "[67,X,2]", "[x,x,x]" };

I need to add data to the dictionary from the above list

Dictionary<int, int> Dict = new Dictionary<int, int>();

so the Dict should contain

Key --> 66 value --> 67

i need to take 66(first value) from first string([66,X,X]) and 67(first value) from second string( [67,X,X]) and add it as a key value pair into the dictionary.

Now i'm following string replacing and looping methodology to do this .

Is there any way to do this in LINQ or Regular expression.

A: 

IF I understand correctly: you want to create linked nodes like 66 -> 67, 67 -> 68, ... n -> n+1?

I would not use LINQ:

private static int GetNumber(string s)
{
    int endPos = s.IndexOf(',');
    return Int32.Parse(s.Substring(1, endPos-1));
}

And in code:

int first, second;    
for (int i = 1; i < TempList.Count; i++)
{
    first = GetNumber(TempList[i - 1]);
    second = GetNumber(TempList[i]);

    Dict.Add(first, second);
}

You should also perform checking, etc.
The sample assumes a list with at least 2 items.

Jaroslav Jandek
+1  A: 

Here is an example using both string.Split() and a Regex:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> data = new List<string>() { "[66,X,X]", "[67,X,2]", "[x,x,x]" };
            addToDict(data);

            Console.ReadKey();
        }

        private static void addToDict(List<string> items)
        {
            string key = items[0].Split('[', ',')[1];
            string val = items[1].Split('[', ',')[1];

            string pattern = @"(?:^\[)(\d+)";
            Match m = Regex.Match(items[0], pattern);
            key = m.Groups[1].Value;
            m = Regex.Match(items[1], pattern);
            val = m.Groups[1].Value;

            _dict.Add(key, val);
        }

        static Dictionary<string, string> _dict = new Dictionary<string, string>();
    }
}

i suspect that your example is quite contrived though, so there may be a better solution especially if you need to process large numbers of strings into key/value pairs (i deliberately hardcoded index values because your example was quite simple and i didn't want to over complicate the answer). If the input data is consistent in format then you can make assumptions like using fixed indexes, but if there is a possibility of some variance then there may need to be more code to check the validity of it.

slugster
+1  A: 

You can use a regular expression to extract the value from each item in the list, and if you want, use LINQ to select out two lists and zip them together (in C# 4.0):

var regex      = new Regex(@"\d+");
var allValues  = TempList.Select(x =>int.Parse(regex.Match(x).Value));
var dictKeys   = allValues.Where((x,index)=> index % 2 == 0); //even-numbered 
var dictValues = allValues.Where((x,index)=> index % 2 > 0); //odd numbered 
var dict       = dictKeys.Zip(dictValues, (key,value) => new{key,value})
                         .ToDictionary(x=>x.key,x=>x.value);

If you're using C# 3.5, you can use Eric Lippert's implementation of Zip().

Mark Cidade
So much LINQ code for such a simple thing. I do not understand why is everyone (pointed at the OP) trying to use LINQ everywhere, unless it is his howework :)
Jaroslav Jandek
It seems like that general impression a lot of people get is that LINQ can be used instead of loops for almost anything, and with less code.
Mark Cidade
+2  A: 

After your comment that you're starting from a list of lists, I understood what you were after. I'm reusing Jaroslav's 'GetNumber' function here. Wrote my sample with array of array of string, but should work just the same. The code below will throw if you have duplicate keys, which I presume is what you want if you're using a dictionary.

        var input = new []
                        {
                            new [] { "[66,X,X]", "[67,X,2]", "[x,x,x]" },
                            new [] { "[5,X,X]", "[8,X,2]", "[x,x,x]" }
                        };

        var query = from l in input
                    select new 
                    {
                     Key = GetNumber(l.ElementAt(0)), 
                     Value = GetNumber(l.ElementAt(1))
                     };

        var dictionary = query.ToDictionary(x => x.Key, x => x.Value);
jeroenh
@ All : Dict.Add(Convert.ToInt32( TempList[0].Split('[', ',')[1]),Convert.ToInt32( TempList[1].Split('[', ',')[1]));
Pramodh
+1. It was hard to decipher what the OP really wants... I have missed the `List<List<>>` comment. If it is what he wants, then LINQ is indeed not a bad approach. Should have named my method `ExtractNumber` or something like that, though.
Jaroslav Jandek
@Pramodh: is it possible to create a less effective and readable (IMHO) approach than that? I would definitely NOT use it like that.
Jaroslav Jandek
@ Jaroslav Jandek : Whats the problem with that. Thats giving the correct output.
Pramodh
@Pramodh you asked for a LINQ or RegEx solution. This is a (clean, IMHO) LINQ solution. The statement you show in your comment certainly works, but it's hardly readable (will you be able to figure out what happens at a glance one year from now?)
jeroenh
A: 
List<List<string>> source = GetSource();

Dictionary<int, int> result = source.ToDictionary(
  tempList => GetNumber(tempList[0]),
  tempList => GetNumber(tempList[1])
);
David B