年終小結之搜房網面試題(一)

          在一個月前,學長就發了搜房網的面試題,仔細一看,好吧,都不會,傻眼了,看來真的是一個小菜鳥中的小菜鳥啊,當時是因爲複習等各種原因,就沒有太注意這些題目,現在考試結束了,就想起來試着把這些題百度一下,歸納一下,來學習學習,嘿嘿嘿嘿。。。。。。

       面試題要求:分爲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在一定條件下更加常用,無非就是互相比較是否相等,這就得看具體的情況具體分析了。。。。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章