iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 5
0

當想要儲存多個物件時,我們會使用Array或List。

List<string> someStrings = new List<string>();

當我們需要List有一些功能時,則會再修改List內容前加上一些邏輯。

Remove duplicate words 中,在把輸入字串拆分成一個一個的單字之後,直覺會想用另外一個陣列來儲存沒有重複的單字,並透過檢查重複的if判斷來去除重複

public string RemoveDuplicatedWord(string text)
{
    var words = text.Split(' ');
    var distinctWords = new List<string>();
    foreach (var word in words)
    {
        if (!distinctWords.Contains(word))
        {
            distinctWords.Add(word);
        }
    }
    return string.Join(" ", distinctWords);
}

此時我們若使用HashSet取代List,讓HashSet的特性幫我們去除重複的物件,就能讓代碼更為精簡。

public string RemoveDuplicatedWord(string text)
{
    
    var words = text.Split(' ');
    var distinctWords = new HashSet<string>(words);
    foreach (var word in words)
    {
        distinctWords.Add(word);
    }
    return string.Join(" ", distinctWords);
}

甚至連for迴圈都可以省去

public string RemoveDuplicatedWord(string text)
{
    var words = text.Split(' ');
    var distinctWords = new HashSet<string>(words);
    return string.Join(" ", distinctWords);
}

Reverse polish notation calculator的例子裡,使用List用來暫時儲存計算結果的operands,在計算完成後會需要移除使用過的運算元。

public double Evaluate(string expressions)
{
    var operatorDict = new Dictionary<string, Func<double, double, double>>()
    {
        {"+", (operator1, operator2) => operator1 + operator2 },
        {"-", (operator1, operator2) => operator1 - operator2 },
        {"*", (operator1, operator2) => operator1 * operator2 },
        {"/", (operator1, operator2) => operator1 / operator2 },
    };

    var operands = new List<double>();
    foreach (var expression in expressions.Split(' '))
    {
        if (operatorDict.ContainsKey(expression))
        {
            var tmp = operatorDict[expression](operands[operands.Count - 2], operands[operands.Count - 1]);
            operands.RemoveAt(operands.Count - 2);
            operands.RemoveAt(operands.Count - 1);
            operands.Add(tmp);
        }
        else
        {
            operands.Add(Double.Parse(expression));
        }
    }

    return operands.First();
}

如果將List改用Stack,則能用Stack First In Last Out的特性,用Pop()達到取出並移除最後一個運算元

public double Evaluate(string expressions)
{
    var operatorDict = new Dictionary<string, Func<double, double, double>>()
    {
        {"+", (operator2, operator1) => operator1 + operator2 },
        {"-", (operator2, operator1) => operator1 - operator2 },
        {"*", (operator2, operator1) => operator1 * operator2 },
        {"/", (operator2, operator1) => operator1 / operator2 },
    };

    var operands = new Stack<double>();
    foreach (var expression in expressions.Split(' '))
    {
        if (operatorDict.ContainsKey(expression))
        {
            operands.Push(operatorDict[expression](operands.Pop(), operands.Pop()));
        }
        else
        {
            operands.Push(Double.Parse(expression));
        }
    }
    
    return operands.First();
}

往後使用List時,不妨多想想需要的List是否還有其他特性,使用適合的資料結構能使代碼簡潔好維護。與Stack相似的資料結構,還有First In First Out的Queue,不妨可以思考一下什麼時候適合使用Queue。


上一篇
Day 4 常見的消除重複
下一篇
Day 6 善用LINQ操作集合
系列文
在Kata中尋找Clean Code是否搞錯了什麼30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言