2010-11-08 63 views
1

我有一個自定義對象的數組。我想能夠由特定數據成員引用該陣列中,例如myArrary["Item1"]如何將關聯索引添加到數組。 c#

「Item1的」實際上是存儲在該自定義類型的名稱屬性的值和我可以寫一個謂詞來標記合適的數組項目。不過,我不清楚如何讓數組知道我想用這個謂詞來查找數組項。

我想爲這個數組使用字典或散列表或NameValuePair,並解決整個問題,但它已生成,它必須保持爲CustomObj[]。我也試圖避免從這個數組中加載一個字典,因爲它會發生很多次,並且可能有很多對象。

爲了澄清

myArray[5] = new CustomObj() // easy! 
myArray["ItemName"] = new CustomObj(); // how to do this? 

可上面做什麼?我真的只是尋找類似的東西DataRow.Columns["MyColumnName"]作品

感謝您的意見。

+0

我沒有看到使用字典的問題,看起來這正是你所需要的... – user472875 2010-11-08 21:19:52

+0

@ user472875字典的問題是當底層數據發生變化時字典的不斷重建。 – 2010-11-08 21:26:08

回答

5

你真正想要的是一個OrderedDictionary. .NET提供在System.Collections.Specialized的版本是不通用的 - 但有一個generic version on CodeProject,你可以使用。在內部,這實際上只是一個與列表結合的散列表,但它以統一的方式暴露出來。

如果你真的想要避免使用字典 - 你將不得不忍受O(n)查找性能的項目按鍵。在這種情況下,堅持使用數組或列表,並使用LINQ Where()方法查找值。取決於是否需要重複條目,您可以使用First()Single()

var myArrayOfCustom = ... 
var item = myArrayOfCustom.Where(x => x.Name = "yourSearchValue").First(); 

這是很容易讓國外消費者不受這方面的知識負擔來包裝這個功能集成到一個類,可以使用簡單的索引來訪問數據。如果您希望經常訪問相同的值,則可以添加memoization等功能。通過這種方式,您可以分攤通過多次訪問構建底層查找字典的成本。

+0

是的,我願意!我可以處理一些限制。我也試圖添加儘可能少的新構造,因爲最終這將在YACC實施中結束。我想我會使用Linq解決方案,我完全忘記了使用(doh!) – Beta033 2010-11-08 22:02:23

0

你可以用這個字典,雖然它可能不是世界上最好的解決方案,這是我第一次想出來的。

Dictionary<string, int> d = new Dictionary<string, int>(); 
    d.Add("cat", 2); 
    d.Add("dog", 1); 
    d.Add("llama", 0); 
    d.Add("iguana", -1); 

的整數可能是對象,你喜歡什麼:)

http://dotnetperls.com/dictionary-keys

+0

Albin是正確的。這是生成並將成爲大型數據集。如果可能的話,我寧願避免將會隨着多次運行而處理的性能命中。如果不可能,我會最終使用這個解決方案。 – Beta033 2010-11-08 21:21:10

0

也許OrderedDictionary是你在找什麼。

+0

謝謝,但我試圖避免重新輸入這些數據來解決將重新打出數千次的性能問題。如果事實證明這是唯一的方法,那麼我會不情願地使用它。我只想讓我的表現更加適應我的表現需求。 – Beta033 2010-11-08 21:23:14

+0

@ Beta033,重新輸入?你的意思是鑄造? – 2010-11-08 21:27:13

+0

有人糾正我,如果我錯了,但我認爲性能命中是可以忽略不計的時候,從對象與參考類型。但是,價值類型需要成本,因爲它們需要(不)裝箱。 – 2010-11-08 21:33:16

2

如果您不想使用「Dictionary」,那麼您應該創建具有數據海量存儲功能的類「myArrary」,併爲索引訪問添加「int」類型索引器,併爲關聯訪問添加「string」類型索引器。

public CustomObj this [string index] 
{ 
    get 
    { 
     return data[searchIdxByName(index)]; 
    } 
    set 
    { 
     data[searchIdxByName(index)] = value; 
    } 
} 

在谷歌的索引首先鏈接:http://www.csharphelp.com/2006/04/c-indexers/

+1

這是不必要的,因爲.NET框架包含一個有序的字典類。它的一個限制是它不是通用的 - 但是CodeProject上有一個公共可用的通用版本。 – LBushkin 2010-11-08 21:21:51

+0

+1這可以使用原始數組作爲內部存儲結構。在搜索字符串時,唯一的警告可能是性能下降。 – 2010-11-08 21:23:11

+0

OrderedDictionary是第一個變體。我認爲作者可能會不喜歡它,並提出一個替代方案。 – Badiboy 2010-11-08 21:56:32

0

您可以使用哈希表;

System.Collections.Hashtable o_Hash_Table = new Hashtable(); 
o_Hash_Table.Add("Key", "Value"); 
0

System.Collections命名空間中有一個名爲Dictionary<K,V>的類,您應該使用它。

var d = new Dictionary<string, MyObj>(); 
MyObj o = d["a string variable"]; 

另一種方法是編寫兩種方法/屬性:

public MyObj this[string index] 
{ 
    get 
    { 
     foreach (var o in My_Enumerable) 
     { 
      if (o.Name == index) 
      { 
       return o; 
      } 
     } 
    } 
    set 
    { 
     foreach (var o in My_Enumerable) 
     { 
      if (o.Name == index) 
      { 
       var i = My_Enumerable.IndexOf(0); 
       My_Enumerable.Remove(0); 
       My_Enumerable.Add(value); 
      } 
     } 
    } 
} 

我希望它能幫助!

0

它取決於集合,有些集合允許通過名稱訪問,有些集合不允許訪問。使用字符串進行訪問僅在集合存儲數據時有意義,列集合通過名稱來標識列,從而允許您通過名稱來選擇列。在一個普通的數組中,這是行不通的,因爲項目只能通過它們的索引號來識別。

0

我最好的建議,如果你不能改變它使用字典,是要麼使用LINQ表達式:

var item1 = myArray.Where(x => x.Name == "Item1").FirstOrDefault(); 

,或者製作一個使用LINQ表達式的擴展方法:

public static class CustomObjExtensions 
{ 
    public static CustomObj Get(this CustomObj[] Array, string Name) 
    { 
     Array.Where(x => x.Name == Name).FirstOrDefault(); 
    } 
} 

然後在您的應用程序:

var item2 = myArray.Get("Item2"); 

然而要注意的表現不會像使用好一個字典,因爲在後臺.NET將循環遍歷列表直到找到一個匹配,所以如果你的列表不會頻繁變化,那麼你可以製作一個字典。

0

我有兩個想法:

1)我不知道你是知道的,但你可以像這樣的字典對象複製到一個數組:

Dictionary dict = new Dictionary(); 
dict.Add("tesT",40); 
int[] myints = new int[dict.Count]; 
dict.Values.CopyTo(myints, 0);

這可能允許您使用Dictionary的一切,同時仍然保持輸出爲一個數組。

2)您也可以實際創建一個DataTable編程方式,如果這就是你想要的確切功能:

DataTable dt = new DataTable(); 
DataColumn dc1 = new DataColumn("ID", typeof(int)); 
DataColumn dc2 = new DataColumn("Name", typeof(string)); 
dt.Columns.Add(dc1); 
dt.Columns.Add(dc2); 
DataRow row = dt.NewRow(); 
row["ID"] = 100; 
row["Name"] = "Test"; 
dt.Rows.Add(row);

你也可以這樣你就不必使表重新創建此方法之外每次。