简体   繁体   English

什么是多维数组的集合?

[英]What is the collection equivalent of a multi-dimensional array?

I've got a group of data that looks like this: 我有一组看起来像这样的数据:

001 001 One
001 002 Two
001 003 Three

002 001 One
002 002 Two
002 003 Three

...

Now, certainly, I could create an array of string[x][y] = z, but this array has to be resizable, and i'd prefer to use the string representations of the indexers than convert to numeric. 现在,当然,我可以创建一个string [x] [y] = z的数组,但是这个数组必须是可调整大小的,我更喜欢使用索引器的字符串表示而不是转换为数字。 The reason is that i will need to look up the data by string, and i don't see the point in needless string->number conversions. 原因是我需要按字符串查找数据,而且我没有看到不必要的字符串 - >数字转换的重点。

My first thought was this: 我的第一个想法是:

Dictionary<string, Dictionary<string, string>> data;

data = new Dictionary<string, Dictionary<string, string>>();

Dictionary<string, string> subdata = Dictionary<string, string>();

subdata.Add(key, string);
data.add(key2, subdata);

and this works, but is somewhat cumbersome. 这有效,但有点麻烦。 It also feels wrong and kludgy and not particularly efficient. 它也感觉错误和kludgy,并不是特别有效。

So what's the best way to store this sort of data in a collection? 那么在集合中存储这种数据的最佳方法是什么?

I also thought of creating my own collection class, but I'd rather not if I don't have to. 我也想过创建我自己的集合类,但是如果我不需要的话我宁愿不这样做。 I'd rather just use the existing tools. 我宁愿只使用现有的工具。

This is pretty common request, and most people end up writing some variation of a Tuple class. 这是非常常见的请求,大多数人最终都会编写一些Tuple类的变体。 If you're using ASP.Net, you can utilize the Triple class that's already available, otherwise, write something like: 如果您使用的是ASP.Net,则可以使用已经可用的Triple类,否则,请执行以下操作:

public class Tuple<T, T2, T3>
{
    public Tuple(T first, T2 second, T3 third)

    {
        First = first;
        Second = second;
        Third = third;
    }

    public T First { get; set; }
    public T2 Second { get; set; }
    public T3 Third { get; set; }

}

There's a generic three-tuple class, so you can create a new List<Tuple<string, string, string>>() and create your tuples and add them. 有一个通用的三元组类,所以你可以创建一个新的List<Tuple<string, string, string>>()并创建你的元组并添加它们。 Expand on that basic class with some indexing functionality and you're up up and away. 使用一些索引功能扩展该基本类,然后你就可以了。

Edit: A list with a dictionary doesn't seem like the correct approach, because each dictionary is only holding one value. 编辑:带有字典的列表似乎不是正确的方法,因为每个字典只保存一个值。 There is no multi-entry relationship between the key and values - there is simply one multi-part key and one associated value. 键和值之间没有多项关系 - 只有一个多部分键和一个关联值。 The data is equivalent to a database row (or tuple!). 数据等同于数据库行(或元组!)。

Edit2: Here's an indexable list class you could use for convenience. Edit2:这是一个可以为方便起见的可索引列表类。

    public class MyTupleList : List<Tuple<string, string, string>>
    {
        public Tuple<string, string, string> this[string first, string second]
        {
            get
            {
                return (this.Find(x => x.First == first && x.Second == second));
            }
            set
            {
                this[first, second] = value;
            }
        }
    }

I think this really depends on what you are modelling here. 我认为这取决于你在这里建模的内容。 If you're planning to use an object-oriented approach, you shouldn't be thinking of these as arbitrary items inside a data structure. 如果您计划使用面向对象的方法,则不应将这些视为数据结构中的任意项。

I'm guessing from looking at this that the first two columns are serving as a "key" for the other items. 我猜这看起来前两列是其他项目的“关键”。 Define a simple struct, and create a dictionary of like so: 定义一个简单的结构,并创建一个类似的字典:

struct Key {
   public int Val1 { get; set; }
   public int Val2 { get; set; }
}

....

Dictionary<Key, string> values;

Obviously Key and the items inside it should be mapped to something closer to what you are representing. 显然Key和它内部的项目应该映射到更接近你所代表的东西。

Given a suitable Pair<A,B> class*, left as an exercise for the reader , you could use a Dictionary<Pair<string, string>, string> . 给定一个合适的Pair<A,B> class *, 作为读者的练习 ,您可以使用Dictionary<Pair<string, string>, string>

* A class with equality and hash code overrides, nothing terribly hard. *具有相等性和哈希码的类会覆盖,没有什么特别难的。

Would a List<List<T>> work for you? List<List<T>>为你工作吗? Still kludgy, but better than dictionaries IMHO. 仍然kludgy,但比字典恕我直言。


EDIT: What about a Dictionary<string,string> and mapping the two keys to a single string? 编辑:如何将Dictionary<string,string>并将两个键映射到单个字符串?

var data = new Dictionary<string,string>(StringComparer.Ordinal);

data[GetKey("002", "001")] = "One";

with

string GetKey(string a, string b) {
    return a + "\0" + b;
}

List<List<string>> is really your best bet in this case. List<List<string>>在这种情况下真的是你最好的选择。 But I agree, it's kludgy. 但我同意,这是愚蠢的。 Personally, I would create a custom class that implements a two-dimensional indexer and maybe use a List<List<T>> internally. 就个人而言,我会创建一个实现二维索引器的自定义类,并可能在内部使用List<List<T>>

For example: 例如:

public class DynamicTwoDimensonalArray<T>
{
  private List<List<T>> Items = new List<List<T>>();

  public T this[int i1, int i2]
  {
    get
    {
      return Items[i1][i2];
    }
    set
    {
      Items[i1][i2] = value;
    }
  }  
}

This is a basic idea to get you going; 这是让你前进的基本想法; clearly the setter needs to deal with bounds issues. 显然,setter需要处理边界问题。 But it's a start. 但这是一个开始。

Edit: 编辑:

No. As I said, I would prefer to index them by string. 不,正如我所说,我宁愿用字符串索引它们。 And they may not always be sequential (might have a missing number in the middle). 并且它们可能并不总是顺序的(中间可能缺少数字)。 - Mystere Man - Mystere Man

Hmm... this is interesting. 嗯......这很有趣。 If that's the case, your best bet would be to create some sort of concatenation of the combination of the two indexers and use that as the key in a single-level dictionary. 如果是这种情况,最好的办法是创建两种索引器组合的某种连接,并将其用作单级字典中的键。 I would still use a custom class to make using the indexing easier. 我仍然会使用自定义类来更轻松地使用索引。 For example: 例如:

public class TwoDimensionalDictionary
{
  private Dictionary<string, string> Items = new Dictionary<string, string>();

  public string this[string i1, string i2]
  {
    get
    {
      // insert null checks here
      return Items[BuildKey(i1, i2)];
    }
    set
    {
      Items[BuildKey(i1, i2)] = value;
    }
  }
  public string BuildKey(string i1, string i2)
  {
    return "I1: " + i1 + " I2: " + i2;
  }  
}

If you are ever going to need to find z by given (x,y) (and not, for example, find all y by given x ), then use this: 如果您需要通过给定(x,y)找到z (x,y)例如,不是通过给定x找到所有y ),那么使用:

Dictionary<KeyValuePair<string, string>, string>

Otherwise, your dictionary is fine as is. 否则,你的字典就好了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM