In SQL illustrations (MSSQL 2005)
Query: SELECT * FROM spt_values;
Expected result: Getting the distinct field value on column name “type”
Solutions: SELECT DISTINCT(type) FROM spt_values;
Implementation on C# .NET
We can use LINQ that already supported since .NET 3.0. But how if we used .NET 2.0?
Let’s see below simple case.
- Class clsHousing
1: /// <summary>2: ///3: /// </summary>4: public class clsHousing5: {6: private string id = String.Empty;7:8: /// <summary>9: ///10: /// </summary>11: public clsHousing(string id)12: {13: if (String.IsNullOrEmpty(id))14: throw new NullReferenceException();15:16: this.id = id;17: this.houseDetails = new List<clsHouseDetail>();18: }19:20: /// <summary>21: ///22: /// </summary>23: public clsHouseDetail[] HouseDetails24: {25: get { return houseDetails.ToArray(); }26: }27: private List<clsHouseDetail> houseDetails = null;28:29: /// <summary>30: ///31: /// </summary>32: /// <returns></returns>33: public override string ToString()34: {35: return this.id;36: }37:38: /// <summary>39: ///40: /// </summary>41: /// <param name="houseDetail"></param>42: public void RegisterHouse(clsHouseDetail houseDetail)43: {44: this.houseDetails.Add(houseDetail);45: }46:47: /// <summary>48: ///49: /// </summary>50: /// <param name="houseDetailID"></param>51: public void UnregisterHouse(string houseDetailID)52: {53: //TODO: Remove from list54: }55: }
- Class clsHouseDetail
1: /// <summary>2: ///3: /// </summary>4: public class clsHouseDetail5: {6: /// <summary>7: ///8: /// </summary>9: public clsHouseDetail()10: { }11:12: /// <summary>13: ///14: /// </summary>15: public string OwnerID16: {17: get { return ownerID; }18: set { ownerID = value; }19: }20: private string ownerID = String.Empty;21:22: /// <summary>23: ///24: /// </summary>25: public enHousingType Type26: {27: get { return type; }28: set { type = value; }29: }30: private enHousingType type = enHousingType.A;31:32: /// <summary>33: ///34: /// </summary>35: /// <returns></returns>36: public override string ToString()37: {38: return (this.OwnerID + " - " + this.Type.ToString());39: }40: }
- Enumeration enHousingType
1: /// <summary>2: ///3: /// </summary>4: public enum enHousingType { A = 1, B = 2, C = 3, D = 4, E = 5 }
- Class clsHousingManager
1: /// <summary>2: ///3: /// </summary>4: public class clsHousingManager5: {6: /// <summary>7: ///8: /// </summary>9: public clsHousingManager()10: {11: this.housing = new List<clsHousing>();12: this.FillSampleValue();13: }14:15: /// <summary>16: ///17: /// </summary>18: public clsHousing[] Housing19: {20: get { return housing.ToArray(); }21: }22: private List<clsHousing> housing = null;23:24: /// <summary>25: ///26: /// </summary>27: private void FillSampleValue()28: {29: clsHousing housing = null;30: clsHouseDetail houseDetail = null;31:32: //Housing-133: housing = new clsHousing("Housing-1");34: // detail-135: houseDetail = new clsHouseDetail();36: houseDetail.OwnerID = "Family-1";37: houseDetail.Type = enHousingType.A;38: housing.RegisterHouse(houseDetail);39:40: // detail-241: houseDetail = new clsHouseDetail();42: houseDetail.OwnerID = "Family-2";43: houseDetail.Type = enHousingType.B;44: housing.RegisterHouse(houseDetail);45:46: // detail-347: houseDetail = new clsHouseDetail();48: houseDetail.OwnerID = "Family-3";49: houseDetail.Type = enHousingType.C;50: housing.RegisterHouse(houseDetail);51:52: // detail-453: houseDetail = new clsHouseDetail();54: houseDetail.OwnerID = "Family-1";55: houseDetail.Type = enHousingType.C;56: housing.RegisterHouse(houseDetail);57:58: this.housing.Add(housing);59: }60:61: /// <summary>62: ///63: /// </summary>64: public void Test()65: {66: clsHousing housing = (this.Housing.Length > 0 ? this.Housing[0] : null);67: if (housing != null)68: {69: //Test distinct of type70: IEnumerable<enHousingType> iEnumHousingType = clsEnumerable.Select<clsHouseDetail, enHousingType>(71: housing.HouseDetails,72: delegate(clsHouseDetail houseDetail) { return houseDetail.Type; }73: );74: iEnumHousingType = clsEnumerable.Distinct<enHousingType>(iEnumHousingType);75: List<enHousingType> listHousingType = new List<enHousingType>(iEnumHousingType);76:77: //Test distinct of owner-ID78: IEnumerable<string> iEnumOwnerID = clsEnumerable.Select<clsHouseDetail, string>(79: housing.HouseDetails,80: delegate(clsHouseDetail houseDetail) { return houseDetail.OwnerID; }81: );82: iEnumOwnerID = clsEnumerable.Distinct<string>(iEnumOwnerID);83: List<string> listOwnerID = new List<string>(iEnumOwnerID);84: }85: }86:87: }
How to get the distinct of property ownerID (string) or type (enHousingType) on class clsHouseDetail on collections?
For simple solutions, we can loop all collections, do checking, stored on temporary variable, and done.
I have other solutions for that.
Static class clsEnumerable
1: /// <summary> Delegate TResult.</summary>2: /// <typeparam name="TSource"></typeparam>3: /// <typeparam name="TResult"></typeparam>4: /// <param name="arg"></param>5: /// <returns></returns>6: public delegate TResult Func<TSource, TResult>(TSource arg);7:8: /// <summary></summary>9: /// <author>Stevanus Ronald</author><date>Wednesday, May 14, 2008</date>10: public static class clsEnumerable11: {12: /// <summary> Select query object.</summary>13: /// <author>Ronald</author><date>Wednesday, May 14, 2008</date>14: /// <typeparam name="TSource"></typeparam>15: /// <typeparam name="TResult"></typeparam>16: /// <param name="source"></param>17: /// <param name="selector"></param>18: /// <returns></returns>19: public static IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector)20: {21: if (source == null)22: throw new ArgumentNullException(source.GetType().ToString());23:24: if (selector == null)25: throw new ArgumentNullException(selector.GetType().ToString());26:27: return SelectIterator<TSource, TResult>(source, selector);28: }29:30: /// <summary> Select iterator query object.</summary>31: /// <author>Ronald</author><date>Wednesday, May 14, 2008</date>32: /// <typeparam name="TSource"></typeparam>33: /// <typeparam name="TResult"></typeparam>34: /// <param name="source"></param>35: /// <param name="selector"></param>36: /// <returns></returns>37: private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector)38: {39: foreach (TSource var in source)40: {41: yield return selector(var);42: }43: }44:45: /// <summary> ToList iterator query object.</summary>46: /// <author>Stevanus Ronald</author><date>Wednesday, May 14, 2008</date>47: /// <typeparam name="TSource"></typeparam>48: /// <param name="source"></param>49: /// <returns></returns>50: private static List<TSource> ToListIterator<TSource>(IEnumerable<TSource> source)51: {52: return new List<TSource>(source);53: }54:55: /// <summary> Distinct query object.</summary>56: /// <author>Stevanus Ronald</author><date>Wednesday, May 14, 2008</date>57: /// <typeparam name="TSource"></typeparam>58: /// <param name="source"></param>59: /// <returns></returns>60: public static IEnumerable<TSource> Distinct<TSource>(IEnumerable<TSource> source)61: {62: return Distinct<TSource>(source, null);63: }64:65: /// <summary> Distinct query object.</summary>66: /// <author>Stevanus Ronald</author><date>Tuesday, June 02, 2009</date>67: /// <typeparam name="TSource"></typeparam>68: /// <param name="source"></param>69: /// <param name="comparer"></param>70: /// <returns></returns>71: public static IEnumerable<TSource> Distinct<TSource>(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)72: {73: if (source == null)74: throw new ArgumentNullException(source.GetType().ToString());75:76: return DistinctIterator<TSource>(source, comparer);77: }78:79: /// <summary> Distinct iterator query object.</summary>80: /// <author>Stevanus Ronald</author><date>Wednesday, May 14, 2008</date>81: /// <typeparam name="TSource"></typeparam>82: /// <param name="source"></param>83: /// <param name="comparer"></param>84: /// <returns></returns>85: private static IEnumerable<TSource> DistinctIterator<TSource>(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)86: {87: Set<TSource> set = new Set<TSource>(comparer, ToListIterator<TSource>(source).Count);88:89: foreach (TSource var in source)90: if (!set.Contains(var))91: {92: set.Add(var);93: yield return var;94: }95: }96:97: }98:99: /// <summary> Internal class Set.</summary>100: /// <author>Stevanus Ronald</author><date>Wednesday, May 14, 2008</date>101: /// <typeparam name="TElement"></typeparam>102: internal class Set<TElement>103: {104: private Int32[] buckets;105: private IEqualityComparer<TElement> comparer;106: private Int32 count;107: private Int32 freeList;108: private Slot[] slots;109:110: /// <summary>111: ///112: /// </summary>113: /// <param name="count"></param>114: public Set(int count)115: : this(null, count)116: { }117:118: /// <summary>119: ///120: /// </summary>121: /// <param name="comparer"></param>122: /// <param name="count"></param>123: public Set(IEqualityComparer<TElement> comparer, int count)124: {125: if (comparer == null)126: comparer = EqualityComparer<TElement>.Default;127:128: this.comparer = comparer;129: this.buckets = new Int32[count];130: this.slots = new Slot[count];131: this.freeList = -1;132: }133:134: /// <summary>135: ///136: /// </summary>137: /// <param name="value"></param>138: /// <returns></returns>139: public bool Add(TElement value)140: {141: return !this.Find(value, true);142: }143:144: /// <summary>145: ///146: /// </summary>147: /// <param name="value"></param>148: /// <returns></returns>149: public bool Contains(TElement value)150: {151: return this.Find(value, false);152: }153:154: /// <summary>155: ///156: /// </summary>157: /// <param name="value"></param>158: /// <param name="add"></param>159: /// <returns></returns>160: private bool Find(TElement value, bool add)161: {162: int hashCode = this.comparer.GetHashCode(value);163: for (int i = 0; i < this.slots.Length ; i++)164: {165: if ((this.slots[i].hashCode == hashCode) && this.comparer.Equals(this.slots[i].value, value))166: {167: return true;168: }169: }170:171: if (add)172: {173: Int32 freeList;174: if (this.freeList > 0)175: {176: freeList = this.freeList;177: this.freeList = this.slots[freeList].next;178: }179: else180: {181: if (this.count == this.slots.Length)182: {183: this.Resize();184: }185: freeList = this.count;186: this.count++;187: }188: Int32 index = this.buckets.Length - 1;189: this.slots[freeList].hashCode = hashCode;190: this.slots[freeList].value = value;191: this.slots[freeList].next = this.buckets[index] - 1;192: this.buckets[index] = freeList + 1;193:194: }195:196: return false;197: }198:199: /// <summary>200: ///201: /// </summary>202: /// <param name="value"></param>203: /// <returns></returns>204: public bool Remove(TElement value)205: {206: int hashCode = this.comparer.GetHashCode(value);207: int index = hashCode % this.buckets.Length;208: int num3 = -1;209: for (int i = this.buckets[index] - 1; i >= 0; i = this.slots[i].next)210: {211: if ((this.slots[i].hashCode == hashCode) && this.comparer.Equals(this.slots[i].value, value))212: {213: if (num3 < 0)214: {215: this.buckets[index] = this.slots[i].next + 1;216: }217: else218: {219: this.slots[num3].next = this.slots[i].next;220: }221: this.slots[i].hashCode = -1;222: this.slots[i].value = default(TElement);223: this.slots[i].next = this.freeList;224: this.freeList = i;225: return true;226: }227: num3 = i;228: }229: return false;230: }231:232: /// <summary>233: ///234: /// </summary>235: private void Resize()236: {237: int num = (this.count * 2) + 1;238: int[] numArray = new int[num];239: Slot[] destinationArray = new Slot[num];240: Array.Copy(this.slots, 0, destinationArray, 0, this.count);241: for (int i = 0; i < this.count; i++)242: {243: int index = destinationArray[i].hashCode % num;244: destinationArray[i].next = numArray[index] - 1;245: numArray[index] = i + 1;246: }247: this.buckets = numArray;248: this.slots = destinationArray;249: }250:251: /// <summary>252: ///253: /// </summary>254: [StructLayout(LayoutKind.Sequential)]255: internal struct Slot256: {257: internal Int32 hashCode;258: internal TElement value;259: internal Int32 next;260: }261:262: }
So to getting the distinct of ownerID:
1: //Test distinct of type2: IEnumerable<enHousingType> iEnumHousingType = clsEnumerable.Select<clsHouseDetail, enHousingType>(3: housing.HouseDetails,4: delegate(clsHouseDetail houseDetail) { return houseDetail.Type; }5: );6: iEnumHousingType = clsEnumerable.Distinct<enHousingType>(iEnumHousingType);7: List<enHousingType> listHousingType = new List<enHousingType>(iEnumHousingType);
And to getting the distinct of type:
1: //Test distinct of owner-ID2: IEnumerable<string> iEnumOwnerID = clsEnumerable.Select<clsHouseDetail, string>(3: housing.HouseDetails,4: delegate(clsHouseDetail houseDetail) { return houseDetail.OwnerID; }5: );6: iEnumOwnerID = clsEnumerable.Distinct<string>(iEnumOwnerID);7: List<string> listOwnerID = new List<string>(iEnumOwnerID);
Have fun!
No comments:
Post a Comment