c#集合类型,保持索引顺序

时间:2014-10-09 18:53:31

标签: c# collections

我有一个包含行的文件  键值

-----+---------------------------
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
..

- 前3个数字是关键并代表比赛,它们是唯一的,它们是升序的 - 浮点值链接到键。例如:第一行的第4个元素(0.39785)属于第1个元素,第6个元素(0.2043)到2个。

我逐行阅读并将其拆分为“”(空格)。 我应该如何存储它(哪个集合/结构)。

假设我想查找“2 1 1”。 当我写的密钥是升序时,不会有像“2 1 1”这样的条目, 只有“1 1 2”,所以首先我必须对它进行排序,但我想得到这些值 在查找的顺序(0.2043 0.39785 0.39785)。

3 个答案:

答案 0 :(得分:2)

以下数据结构应满足您的所有要求:

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

使用原始数据中的LINQ创建上述结构的实例应该很容易。

访问应该很简单:

  1. 从2,1,1创建HashSet(2,1)
  2. Dictionary - &gt;中查找(2,1) ((1,0.39785),(2,0.2043))
  3. 使用部分密钥查找double,如2 - &gt; 0.2043
  4. CAVEAT 解决方案只能在int一行的相同double - 值上运行 - 值也相同。 (这似乎适用于提供的样本数据)。

    编辑创建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);
    

答案 1 :(得分:0)

有趣的问题。我创建了这个类:

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>>();
}

通过在Add中添加6元组,它对整数进行排序并将它们连接到唯一键字符串(例如1_1_2)。双打插入查找字典中。一些键可以在这里多次设置,但由于它们的int-&gt;双关联在一行中是相同的,因此无关紧要。

Find访问以相应的方式发生。

答案 2 :(得分:0)

[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;
    }