【问题标题】:Linq Conditional .Any() SelectLinq 条件 .Any() 选择
【发布时间】:2013-08-17 01:29:59
【问题描述】:

如何对列值执行条件选择,我对返回的值有偏好。如果我找不到最佳选择,我会选择下一个,如果有的话,然后如果不是下一个,等等。现在看起来,总共需要 3 个查询。有没有办法进一步简化?

var myResult = string.Empty;

if (myTable.Where(x => x.ColumnValue == "Three").Any())
{
    myResult = "Three"; // Can also be some list.First().Select(x => x.ColumnValue) if that makes it easier;
}
else if (myTable.Where(x => x.ColumnValue == "One").Any())
{
    myResult = "One";
}
else if (myTable.Where(x => x.ColumnValue == "Two").Any())
{
    myResult = "Two";
}
else
{
    myResult = "Four";
}

【问题讨论】:

  • 除此之外,您还可以将 lamda 传递给 Any,`.Any(x => x.ColumnValue == "Two")。
  • 仅供参考 - 你不需要 .Where: .Any(x => x.ColumnValue == "Three")

标签: c# linq


【解决方案1】:

您可以根据自己的喜好使用string[]

string[] prefs = new[]{ "One", "Two", "Three" };
string myResult = prefs.FirstOrDefault(p => myTable.Any(x => x.ColumnValue == p));
if(myResult == null) myResult = "Four";

编辑Enumerable.Joinvery efficient哈希表方法,也只需要一次查询:

string myResult = prefs.Select((pref, index) => new { pref, index })
    .Join(myTable, xPref => xPref.pref, x => x.ColumnValue, (xPref, x) => new { xPref, x })
    .OrderBy(x => x.xPref.index)
    .Select(x => x.x.ColumnValue)
    .DefaultIfEmpty("Four")
    .First();

Demo

【讨论】:

  • 在最坏的情况下仍然执行三个查询,不是吗?
  • @SimonBelanger:我认为 OP 要求一种使代码更具可读性的方法(“进一步简化”)。如果列表实际上很长,它也更易于维护。
  • @SimonBelanger:添加了另一种可读性较低但效率更高的方法。
  • 您确定可以将JoinString[] 转换为DbSet 吗? (我猜 OP 可能没有使用实体框架,但问题中的术语表明他是......)
  • @SteveRuble:我认为他可以使用WHERE(x => prefs.Contains(x.ColumnName))然后让数据库优化。
【解决方案2】:

我写了一个扩展方法,有效地反映了 Tim Schmelter 的回答(他发布更新时正在测试这个。:-()

public static T PreferredFirst<T>(this IEnumerable<T> data, IEnumerable<T> queryValues, T whenNone)
{
    var matched = from d in data
                  join v in queryValues.Select((value,idx) => new {value, idx}) on d equals v.value
                  orderby v.idx
                  select new { d, v.idx };

    var found = matched.FirstOrDefault();

    return found != null ? found.d : whenNone;
}

// usage:
myResult = myTable.Select(x => x.ColumnValue)
                  .PreferredFirst(new [] {"Three", "One", "Two"}, "Four");

我写了一篇会更早退出的文章:

public static T PreferredFirst<T>(this IEnumerable<T> data, IList<T> orderBy, T whenNone)
{
    // probably should consider a copy of orderBy if it can vary during runtime
    var minIndex = int.MaxValue;

    foreach(var d in data)
    {
         var idx = orderBy.IndexOf(d);

         if (idx == 0) return d;  // best case; quit now

         if (idx > 0 && idx < minIndex) minIndex = idx;
    }

    // return the best found or "whenNone"
    return minIndex == int.MaxValue ? whenNone : orderBy[minIndex];
}

【讨论】:

    【解决方案3】:

    我在 SQL 中使用加权方法,为每个条件值分配权重。然后通过根据您的订购方案找到最高或最低重量来找到解决方案。

    下面是等效的 LINQ 查询。请注意,在此示例中,我为较低的权重分配了较高的优先级:

    void Main()
    {
        // Assume below list is your dataset 
        var myList =new List<dynamic>(new []{
        new {ColumnKey=1, ColumnValue  ="Two"},
        new {ColumnKey=2, ColumnValue  ="Nine"},
        new {ColumnKey=3, ColumnValue  ="One"},
        new {ColumnKey=4, ColumnValue  ="Eight"}});
    
        var result = myList.Select(p => new 
                                {
                                    ColVal =    p.ColumnValue,
                                    OrderKey =  p.ColumnValue == "Three" ? 1 : 
                                                p.ColumnValue == "One"   ? 2 : 
                                                p.ColumnValue == "Two"   ? 3 : 4
                                 }).Where(i=> i.OrderKey != 4)
                                 .OrderBy(i=>i.OrderKey)
                                 .Select(i=> i.ColVal)
                                 .FirstOrDefault();
    
        Console.WriteLine(result ?? "Four");
    }
    

    【讨论】:

      【解决方案4】:

      这样的事情怎么样:

      var results = myTable.GroupBy(x => x.ColumnValue).ToList();
      
      if (results.Contains("Three")) {
          myResult = "Three"; 
      } else if (results.Contains("One")) {
          myResult = "One";
      } else if (results.Contains("Two")) {
          myResult = "Two";
      } else {
          myResult = "Four";
      }
      

      【讨论】:

      • 不妨在一个哈希表中执行它并执行 O(1) 查找(我的意思是没有分组)
      猜你喜欢
      • 2020-08-01
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-06
      • 1970-01-01
      相关资源
      最近更新 更多