C # collection type to keep index order

I have a file with strings of key values

-----+---------------------------
1 1 2 0.39785 0.39785 0.2043 36
1 1 3 0.409604 0.409604 0.180792 24
1 1 4 0.407281 0.407281 0.185438 24
1 1 5 0.404958 0.404958 0.190084 24
1 1 6 0.403399 0.403399 0.193203 24
...
23 34 36 0.414457 0.354921 0.230622 576
..

      

- the first 3 numbers are keys and represent a match, they are unique and they are ascending - - float values ​​are associated with keys. for example: the first element of the 4th element (0.39785) refers to the key 1, the 6th element (0.2043) is 2.

I read this line by line and split it by "" (space). How to store it (what collection / structure).

Let's say I want to search for "2 1 1". Since I wrote that the keys are ascending, there will be no entry like "2 1 1", only "1 1 2", so I need to sort it first, but I want to get the values ​​in the search order (0.2043 0.39785 0.39785).

+3


source to share


3 answers


The data structure below should meet all your requirements:

Dictionary<HashSet<int>, Dictionary<int, double>>

      

Directly instantiate the above structure with LINQ from source data.

Access should be simple:



  • from 2, 1, 1 create HashSet

    (2, 1)
  • search (2, 1) in -> Dictionary

    ((1, 0.39785), (2, 0.2043))
  • with partial key search a double

    like 2 -> 0.2043

CAVEAT The solution will only work if for identical int

-values ​​on the same line the values ​​are double

also identical. (Which appears to be true for the sampled data provided).

EDIT Code to create yourLookup

:

List<List<int>> intList = new List<List<int>>() {
   new List<int> () {1, 1, 2}, 
   new List<int> () {1, 1, 3},
   ...
};

List<List<double>> doubleList = new List<List<double>> {
    new List<double>() {0.39785, 0.39785, 0.2043},
    new List<double>() {0.409604, 0.409604, 0.180792},
    ....
};

var dictionaries = intList.Zip(doubleList, (Is, Ds) =>
    { return Is.Zip(Ds, (i, d) => new KeyValuePair<int, double>(i, d)).Distinct()
        .ToDictionary(kv => kv.Key, kv => kv.Value); });

var yourLookup = dictionaries.Select(
    dictionary => new { hashset = new HashSet<int>(dictionary.Keys), dictionary })
        .ToDictionary(x => x.hashset, x => x.dictionary);

      

+2


source


An interesting problem. I created this class:

class Mapper
{
    public void Add(int n1, int n2, int n3, double f1, double f2, double f3)
    {
        int[] intArray = new int[] {n1,n2, n3};
        Array.Sort(intArray);
        Dictionary<int, double> dict = new Dictionary<int, double>();
        dict[n1] = f1;
        dict[n2] = f2;
        dict[n3] = f3;

        myDictionary[string.Join("_", intArray.Select(i=>i.ToString()))] = dict;
    }

    public Tuple<double, double, double> Find(int n1, int n2, int n3)
    {
        string key = CreateKey(n1, n2, n3);

        if (!myDictionary.ContainsKey(key))
            return null;

        Dictionary<int, double> found = myDictionary[key];

        return new Tuple<double, double, double>(found[n1], found[n2], found[n3]);
    }

    private string CreateKey(int n1, int n2, int n3)
    {
        int[] intArray = new int[] { n1, n2, n3 };
        Array.Sort(intArray);
        return string.Join("_", intArray.Select(i => i.ToString()));
    }

    private Dictionary<string, Dictionary<int, double>> myDictionary = new Dictionary<string, Dictionary<int, double>>();
}

      



By adding a 6-tuple to Add

, it sorts the integers and concatenates them to a unique key string (e.g. 1_1_2). Duplicate items are inserted into the search dictionary. Some keys can be set multiple times here, but since they are double associations on the same line, it doesn't matter.

Access to it Find

takes place accordingly.

0


source


[TestMethod]
public void test()
{
    var data = new string[]{
        "1 1 2 0.39785 0.39785 0.2043 36",
        "1 1 3 0.409604 0.409604 0.180792 24",
        "1 1 4 0.407281 0.407281 0.185438 24",
        "1 1 5 0.404958 0.404958 0.190084 24",
        "1 1 6 0.403399 0.403399 0.193203 24"
    };
    var dic = new FloatLookup(data);
    var test1 = dic.GetValues(211).ToArray();
    CollectionAssert.AreEquivalent(new float[] { 0.39785F, 0.39785F, 0.2043F }, test1);
    var test2 = dic.GetValues(121).ToArray();
    CollectionAssert.AreEquivalent(new float[] { 0.39785F, 0.2043F, 0.39785F  }, test2);
    var test3 = dic.GetValues(611).ToArray();
    CollectionAssert.AreEquivalent(new float[] { 0.193203F, 0.403399F, 0.403399F }, test3);
}

class FloatLookup
{

    Dictionary<int, KeyValuePair<int, float>[]> dic;

    public FloatLookup(string[] data)
    {
        dic = data.Select(GetKeyValuePair).
            ToDictionary(o => o.Key, o => o.Value);
    }

    public IEnumerable<float> GetValues(int num)
    {
        return GetValues(GetInts(num));
    }

    public IEnumerable<float> GetValues(IEnumerable<int> ints)
    {
        var key = GetKey(ints);
        KeyValuePair<int, float>[] kvps = null;
        if (!dic.TryGetValue(key, out kvps))
            yield break;
        foreach (var i in ints)
            yield return kvps.First(o => o.Key == i).Value;
    }

    static KeyValuePair<int, KeyValuePair<int, float>[]> GetKeyValuePair(string line)
    {
        var items = line.Split(' ');
        var ints = new string[] { items[0], items[1], items[2] }.
            Select(o => int.Parse(o)).ToArray();
        var floats = new string[] { items[3], items[4], items[5] }.
            Select(o => float.Parse(o)).ToArray();
        var kvps = Enumerable.Range(0, 3).Select(o =>
            new KeyValuePair<int, float>(ints[o], floats[o])).Distinct().ToArray();
        var key = GetKey(ints);
        return new KeyValuePair<int, KeyValuePair<int, float>[]>(key, kvps);
    }

    static int[] GetInts(int num)
    {
        return num.ToString().ToCharArray().Select(o => 
            int.Parse(o.ToString())).ToArray();
    }

    static int GetKey(IEnumerable<int> ints)
    {
        var ret = 0;
        var ary = ints.ToArray();
        Array.Sort(ary);
        var c = 1;
        for (int i = ary.GetUpperBound(0); i > -1; i--)
        {
            ret += ary[i] * c;
            c *= 10;
        }
        return ret;
    }

      

0


source







All Articles