簡體   English   中英

我怎樣才能使這個 linq 查詢更清晰、更可重用?

[英]How can i make this linq query cleaner and more reusable?

我有一個 linq 查詢,它返回幾個環大小的計數。 然而,即使它在某種程度上可以重復使用,我也想看看我是否可以改進它。

    private async Task<RingSizeLettersDto> CountOfLettersByRingFingerAsync(Func<RingSize, string> selector)
    {
        var ringSizes = await _ringSizeRepository.Get();

        RingSizeLettersDto ringSizeLetters = new RingSizeLettersDto();

        ringSizeLetters.G = ringSizes.Where(x => selector(x) == "G").Count();
        ringSizeLetters.H = ringSizes.Where(x => selector(x) == "H").Count();
        ringSizeLetters.I = ringSizes.Where(x => selector(x) == "I").Count();
        ringSizeLetters.J = ringSizes.Where(x => selector(x) == "J").Count();
        ringSizeLetters.K = ringSizes.Where(x => selector(x) == "K").Count();
        ringSizeLetters.L = ringSizes.Where(x => selector(x) == "L").Count();
        ringSizeLetters.M = ringSizes.Where(x => selector(x) == "M").Count();
        ringSizeLetters.N = ringSizes.Where(x => selector(x) == "N").Count();
        ringSizeLetters.O = ringSizes.Where(x => selector(x) == "O").Count();
        ringSizeLetters.P = ringSizes.Where(x => selector(x) == "P").Count();
        ringSizeLetters.Q = ringSizes.Where(x => selector(x) == "Q").Count();
        ringSizeLetters.R = ringSizes.Where(x => selector(x) == "R").Count();
        ringSizeLetters.S = ringSizes.Where(x => selector(x) == "S").Count();
        ringSizeLetters.T = ringSizes.Where(x => selector(x) == "T").Count();
        ringSizeLetters.U = ringSizes.Where(x => selector(x) == "U").Count();
        ringSizeLetters.V = ringSizes.Where(x => selector(x) == "V").Count();
        ringSizeLetters.W = ringSizes.Where(x => selector(x) == "W").Count();
        ringSizeLetters.X = ringSizes.Where(x => selector(x) == "X").Count();
        ringSizeLetters.Y = ringSizes.Where(x => selector(x) == "Y").Count();
        ringSizeLetters.Z = ringSizes.Where(x => selector(x) == "Z").Count();
        ringSizeLetters.Z1 = ringSizes.Where(x => selector(x) == "Z1").Count();
        ringSizeLetters.Z2 = ringSizes.Where(x => selector(x) == "Z2").Count();
        ringSizeLetters.Z3 = ringSizes.Where(x => selector(x) == "Z3").Count();
        ringSizeLetters.Z4 = ringSizes.Where(x => selector(x) == "Z4").Count();
        ringSizeLetters.Z5 = ringSizes.Where(x => selector(x) == "Z5").Count();
        ringSizeLetters.Z6 = ringSizes.Where(x => selector(x) == "Z6").Count();
        ringSizeLetters.NA = ringSizes.Where(x => selector(x) == "N/A").Count();

        return ringSizeLetters;

    }

我必須牢記改進:

  • 您可以使用Count(x => selector(x) == "G") ,這將減少每行 1 個方法調用。

  • 您可以創建一個Dictionary<string, int> (可能char as key 可能更准確),它表示按字符計數,然后在應用程序的其他地方,您可以使用要搜索的字符作為鍵來訪問它:

var ringSizes = new[] { 1, 2, 2 };
var ringSizeLetters = ringSizes.GroupBy(x => Selector(x))
     .ToDictionary(x => x.Key, v => v.Count());

var ocurrences = ringSizeLetters["A"];


根據您的特定用例是否允許這樣做,更簡潔的解決方案是使用字典。 從你的代碼來看,最好的類型是IDictionary<string, int> 在這里,字符串鍵是標識符(例如 'Z1'),整數值是.Count()的結果。

我在下面列出了一個可能的代碼示例;

public static IDictionary<string, int> GetRingSizeLettersAsDict(
    IEnumerable<string> sizeLetters,
    IEnumerable<object> ringSizes)
{
    IDictionary<string, int> ringSizeLetters = new();

    sizeLetters.Select(
        sl => ringSizeLetters.Add(
            sl,
            ringSizes.Where(rs => selector(rs).Equals(sl)).Count())
    );

    return ringSizeLetters;
}

這只是眾多解決方案之一,但它應該與您的代碼示例相同,前提是它適合您的用例。

這是一種偽代碼,但這樣的事情應該可以解決問題..

它是通過 System.Reflection 完成的

                PropertyInfo[] properties = ringSizeLetters.GetProperties();
                foreach (PropertyInfo property in properties)
                {
                   var propertyName = property.Name;
                   var ringsizeValue = ringSizes.SingleOrDefault(x=> x.PROPERTYNAME == propertyName)
    
                   // if it finds ringsize Value 
                  if(ringsizeValue != null)
                  {
                     property.SetValue(ringSizeLetters, ringsizeValue.Count());
                  }
    
                }

如果您真的想要它們,您可以保留所有屬性:

class RingSizeDto{

  public int G { get; set;}
  public int H { get; set;}

...並通過使用例如字典來支持它們來避免反射:

class RingSizeDto{

  private Dictionary<string, int> _ringSizes = new();

  public int G { get => _ringSizes[nameof(G)]; set _ringSizes[nameof(G)] = value; }
  public int H { get => _ringSizes[nameof(H)]; set _ringSizes[nameof(H)] = value; }
  ...

這意味着可以通過提供字典一次性設置大小:

  public RingSizeDto(Dictionary <string, int> sizes){
    _ringSizes = sizes;
  }

字典可以通過查詢生成,例如

var sizes = someSizeList.GroupBy(s => s.SizeLetter).ToDictionary(g => g.Key, g => g.Count());

new RingSizeDto(sizes);

筆記; 如果您的列表沒有所有可能的大小,您將希望通過使用 TryGetValue 來避免字典訪問崩潰

public int G { get => _ringSizes.TryGetValue(nameof(G), out var x) ? x : 0; set _ringSizes[nameof(G)] = value; }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM