在一個月前,學長就發了搜房網的面試題,仔細一看,好吧,都不會,傻眼了,看來真的是一個小菜鳥中的小菜鳥啊,當時是因爲複習等各種原因,就沒有太注意這些題目,現在考試結束了,就想起來試着把這些題百度一下,歸納一下,來學習學習,嘿嘿嘿嘿。。。。。。
面試題要求:分爲4個檔次,0-40 淘汰;40-60 初級;60-80中級,80-100高級
【01】不使用數據庫,怎麼通過程序實現快速的排重計算。
a.加載數據到集合中,然後使用Linq中的Distinct()進行去重
注:好吧,我也不知道Distinct方法是什麼,真的不熟,於是度娘了。。。
Distinct 方法中使用的相等比較器。這個比較器需要重寫Equals和GetHashCode方法,個人不推薦,感覺較麻煩,需要些多餘的類,並且用起來還要實例化一個比較器,當然自己也可以寫一個泛型的比較器生成工廠用來專門生成比較器,但仍然覺得較麻煩。
1.下面的示例演示如何實現可以在 Distinct 方法中使用的相等比較器。
public class Product
{
public string Name { get; set; }
public int Code { get; set; }
}
// Custom comparer for the Product class
class ProductComparer : IEqualityComparer<Product>
{
// Products are equal if their names and product numbers are equal.
public bool Equals(Product x, Product y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the products' properties are equal.
return x.Code == y.Code && x.Name == y.Name;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Product product)
{
//Check whether the object is null
if (Object.ReferenceEquals(product, null)) return 0;
//Get hash code for the Name field if it is not null.
int hashProductName = product.Name == null ? 0 : product.Name.GetHashCode();
//Get hash code for the Code field.
int hashProductCode = product.Code.GetHashCode();
//Calculate the hash code for the product.
return hashProductName ^ hashProductCode;
}
}
注:1.Object.ReferenceEquals()方法,確定指定的object實例是否是相同的實例。即測試兩個對象的引用是否是相同的引用。
2.實現此比較器後,您可以使用 Distinct 方法中 Product 對象的序列,如下面的示例所示。
Product[] products = { new Product { Name = "apple", Code = 9 },
new Product { Name = "orange", Code = 4 },
new Product { Name = "apple", Code = 9 },
new Product { Name = "lemon", Code = 12 } };
//Exclude duplicates.
IEnumerable<Product> noduplicates =
products.Distinct(new ProductComparer());
foreach (var product in noduplicates)
Console.WriteLine(product.Name + " " + product.Code);
/*
This code produces the following output:
apple 9
orange 4
lemon 12
*/
由此可知,在使用這個方法的時候就必須在要使用的類中重寫Equals和GetHashCode方法,再進行排重,這樣做,好麼?????保留疑問。。。。
在網上還有一種更方便的方法,記錄如下。
自己擴展一個DistinctBy。這個擴展方法還是很不錯的,用起來很簡潔,適合爲框架添加的Distinct擴展方法。
public static IEnumerable<TSource> DistinctBy<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
使用方法如下(針對ID,和Name進行Distinct):
var query = people.DistinctBy(p => new { p.Id, p.Name });
若僅僅針對ID進行distinct:
var query = people.DistinctBy(p => p.Id);
這僅僅是方法a啊,這麼複雜,還是我知道的太少了啊。唉。。。
b.如果明確是哪幾列中重複的數據的話,可以通過將數據加載到table中,在過濾table的方式來進行去重。
獲取對固定列不重複的新DataTable#region 獲取對固定列不重複的新DataTable
/// <summary>
/// 獲取對固定列不重複的新DataTable
/// </summary>
/// <param name="dt">含有重複數據的DataTable</param>
/// <param name="colName">需要驗證重複的列名</param>
/// <returns>新的DataTable,colName列不重複,表格式保持不變</returns>
private DataTable GetDistinctTable(DataTable dt, string colName)
{
if (dt.Rows.Count == 0 || dt.Rows.Count == 1)
{
WriteFile("GetDistinctTable傳入dt的行數小於等於1" + "\r\n", logName, out outMessage);
return dt;
}
DataView dv = dt.DefaultView;
//dv過濾dv中的重複列名
DataTable dtCardNo = dv.ToTable(true, colName);
DataTable Pointdt = new DataTable();
//ToTable()根據現有 DataView 中的行,創建並返回一個新的 DataTable。
//輸出表與輸入表包含相同的列
Pointdt = dv.ToTable();
Pointdt.Clear();
for (int i = 0; i < dtCardNo.Rows.Count; i++)
{
try
{
//dr取的是Select返回的DataRow[]中的第一條數據
//如果dtCardNo.Rows[i][0].ToString()中沒有值會報數組超出索引界限的錯誤
if (!string.IsNullOrEmpty(dtCardNo.Rows[i][0].ToString()))
{
DataRow dr = dt.Select(colName + "='" + dtCardNo.Rows[i][0].ToString() + "'")[0];
//DataRow.ItemArray通過一個數組來獲取或設置此行的所有值
Pointdt.Rows.Add(dr.ItemArray);
}
}
catch (Exception ee)
{
//可以將錯誤寫入日誌文件
}
}
return Pointdt;
}
#endregion
這個方法只作用於知道哪幾個列會有重複的情況下。有一定的侷限性。
很明顯,方法a具有通用性,而方法b在一定條件下更加常用,無非就是互相比較是否相等,這就得看具體的情況具體分析了。。。。