Pregunta

I'm still fairly new to using Dictionaries so I need some help. At the the moment I have the following string getting loaded in from a third party device:

26291,0.04760144554139385,18087,0.1990775029361712,41972,2.208226792687473, 26291,18087,41972,

What this is, is two different values getting sent over. The first and second number (separated by the comma) are tied to one device, the third and fourth to another and so on. The odd numbers are constant where the even number varies every update. These are also sent in an array where the smallest odd number is sent first.

In my other program I need to tied these to individual objects regardless of how they are sent in the array. I know that dictionaries work with key values and with the above even numbers being perfect for this.

However, I've never created a dictionary with dynamic keys and values. Could someone show me how this could be done in c#?

Before what I was doing was passing over a single value and adding it to a string array in my other program, separating them with the comma. This new way I want to try, is a little out of my knowledge depth, so if someone could point me in the right direction, I would appreciate it.

Here is a code snippet of how I'm generating the above string from my iOS program:

    for (ESTBeacon *b in beacons)
    {
        NSString *currentBeaconDistance = [self sendBeaconDistanceToUnity:index WithBeacon:b FromBeacons:beacons];
        index++;

        self.currentBeaconsString = [self.currentBeaconsString stringByAppendingString:currentBeaconDistance];
        self.currentBeaconsString = [self.currentBeaconsString stringByAppendingString:@","];


        NSString *beaconPower =[self sendBeaconMajorToUnity:index WithBeacon:b FromBeacons:beacons];
        index++;

        self.beaconMajorString = [self.beaconMajorString stringByAppendingString:beaconPower];
        self.beaconMajorString = [self.beaconMajorString stringByAppendingString:@","];

        self.combinedString = [self.combinedString stringByAppendingString:beaconPower];
        self.combinedString = [self.combinedString stringByAppendingString:@","];
        self.combinedString = [self.combinedString stringByAppendingString:currentBeaconDistance];
        self.combinedString = [self.combinedString stringByAppendingString:@","];

    }

Which is then passed into Unity via UnitySendMessage. To use the above data I was doing the following:

public void DistanceValue(string message)
{

    fooString = message.Split (',');

    if (fooString.Contains("-1")) 
    {
        return;
    }

   distance_String = message;
}

The above way lets me have any number of objects being sent over as long as they are detected. The sample string is from 3 devices that were detected, but it could just as easily show 8 devices etc as long as they are within range of my iPad.

¿Fue útil?

Solución

You want to split on comma and then add the key value pairs into a Dictionary<string, string>

Something like:

string input = "26291,0.04760144554139385,18087,0.1990775029361712,41972,2.208226792687473, 26291,18087,41972,";

var d = new Dictionary<string, string>();

var split = input.Split(new char[] {','});

if (split.Count(x => x == ",") % 2 == 0)
{
    throw new ArgumentException("Input is not key value pair.");
}

int i = 0;
while (i <= split.Length)
{
    try
    {
        d.Add(split[i], split[i + 1]);

        ParseToDouble(numbers, split, i);

        i = i + 2;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

/// <summary>
/// Attempts to Parse string to double. Adds to dictionary if successful. Does nothing if fails to parse.
/// </summary>
/// <param name="numbers">The dictionary of numbers</param>
/// <param name="split">The raw input</param>
/// <param name="i">The iterator</param>
private static void ParseToDouble(Dictionary<double, double> numbers, string[] split, int i)
{
    double key;
    bool keySuccess = double.TryParse(split[i], out key);

    double value;
    bool valueSuccess = double.TryParse(split[i + 1], out value);

    if (keySuccess && valueSuccess)
    {
        numbers.Add(key, value);
    }
}

Dictionaries have unique keys so you need to think about what you'd like to do if your input has duplicate keys. In your example, the key "26291" is duplicated so cannot be added to the dictionary again. If you want non-unique keys, you'll need

List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>()

// Add
list.Add(new KeyValuePair<string, string>("key", "value"));

Note KeyValuePair Key and Value properties are readonly.

Otros consejos

You can use a regular expression to parse a single line into a dictionary of key-value pairs:

var line = "26291,0.04760144554139385,18087,0.1990775029361712,41972,2.208226792687473,";
var regex = new Regex(@"(?<key>\d+),(?<value>\d+\.\d+),");
var dictionary = regex
  .Matches(line)
  .Cast<Match>()
  .ToDictionary(
    match => match.Groups["key"].Value,
    match => Double.Parse(match.Groups["value"].Value, CultureInfo.InvariantCulture)
  );

The dictionary then contains the following data:

Key   | Value
------+-------------------
26291 | 0.0476014455413939 
18087 | 0.199077502936171 
41972 | 2.20822679268747 

I created the regular expression with the following assumptions:

  • The key is a non-negative integer
  • The value is a non-negative floating point number with digits both before and after the dot
  • Keys and values are separated by a comma and the value is also terminated by a comma

You may have to adjust the code slightly if some of these assumptions are incorrect.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top