LINQ - BETWEEN "a" AND "e"

本文关键字:quot AND LINQ BETWEEN | 更新日期: 2023-09-27 18:18:30

我有一个学生的通用列表。我想在LINQ的帮助下过滤学生名字开头的between "a" and "e"

Students = Students.Where(s => s.Name.Substring(0, 1) == "a" 
                            && s.Name.Substring(0, 1) == "e").ToList();

LINQ - BETWEEN "a" AND "e"

未经此测试可能有效:

Students = Students.Where(s => s.Name.Substring(0, 1) >= "a" 
                        && s.Name.Substring(0, 1) <= "e").ToList();

或者

Students = Students.Where(s => ["a", "b", "c", "d", "e"]
                               .contains(s.Name[0]).ToList();

由less/greater定义的范围,而不仅仅是==:

 Students = Students.Where(s => s.Name.Substring(0, 1) >= "a" 
                        && s.Name.Substring(0, 1) <= "e").ToList();

您也可能希望小写或比较两种情况

有多种方法。这里有两个:

您仍然可以使用原始代码,但将相等性检查转换为范围检查:

Students = Students.Where(s => s.Name[0] >= 'a' && s.Name[0] <= 'e');

或者,您也可以直接使用ASCII值:

Students = Students.Where(s => s.Name[0] >= 97 && s.Name[0] <= 101);

请注意,我们在这里使用Name[0]而不是Substring,所以我们可以得到字母的char/int值,而不是string


如果两个字符不相邻,则可以使用另一种方法,即创建一个列表并检查第一个字母是否包含在该列表中:

string[] chars = { "a", "b", "c", "d", "e" };
Students = Students.Where(s => chars.Contains(s.Name.Substring(0, 1)));

我将通过添加一个方法来实现这一点,该方法将字符转换为int型,然后可以比较其ASCII值:

private static bool StartsWithRange(string value, char first, char last)
{
  if (string.IsNullOrEmpty(value))
  {
    return false;
  }
  if (first > last)
  {
    throw new ArgumentException(string.Format("'{0}' shouldn't come after '{1}'.", first, last), nameof(last));
  }
  int intValue = value.ToLower()[0];
  return intValue >= first && intValue <= last;
}

用法:

Students.Where(s => StartsWithRange(s, 'a', 'e')).ToList();

我测试了不同的情况,它似乎工作:

Assert.IsFalse(StartsWithRange("abcd", 'd', 'e'));
Assert.IsTrue(StartsWithRange("dcd", 'd', 'e'));
Assert.IsTrue(StartsWithRange("Dcd", 'd', 'e'));
Assert.IsTrue(StartsWithRange("ebcd", 'd', 'e'));
Assert.IsTrue(StartsWithRange("Ebcd", 'd', 'e'));
Assert.IsFalse(StartsWithRange("fbcd", 'd', 'e'));
Assert.IsFalse(StartsWithRange("Fbcd", 'd', 'e'));
Assert.IsFalse(StartsWithRange(string.Empty, 'd', 'e'));

请注意ToLower -调用,如果不是所有的value都在相同的情况下,这是必需的。

如果值都在一行中,如果它们只是"随机"字母,那么我将使用如上所述的数组方法。

我希望你使用正则表达式。

students = students.Where(x => Regex.IsMatch(x.Name, @"^[a-e].*", RegexOptions.IgnoreCase) == true).ToList();

在这里,您可以看到我使用了正则表达式@"^[a-e].*"来指示我们必须对名字以a,b,c,d,e开头的学生的名字进行mach。所以你可以很容易地修改你的过滤器来获取学生。

注意:请包含名称空间using System.Text.RegularExpressions;,以便在您的项目中使用正则表达式

我会用你给的信息来做这件事。

var s = new [] {"a","b","c","d","e"};
Students = Students.Where(s => s.Contains(s.Name.Substring(0, 1))).ToList();

希望我理解正确。

Students = Students.Where(s => {
   char c = s.Name[0];
   return (c >= 'a' && c <= 'e') || (c >= 'A' && c <= 'E') ;
}).ToList();

我还包括大写字母

在不使用其他字符串操作方法的情况下完成此操作的最简单方法之一是:

var filter = Students.Where(s => s!= null && s [0] >= 'a' && s[0] <= 'e').ToList();

您可以使用string.CompareOrdinal方法。

Students = Students.Where(s => 
string.CompareOrdinal(s.Name.Substring(0, 1), "a") >= 0 && string.CompareOrdinal(s.Name.Substring(0, 1), "e") <= 0)
.ToList();

它将包括"a"answers"e"。您可以在比较之前使用大写转换,也可以用于不区分大小写的比较。

我会考虑实现一个Between扩展方法并使用它。

代码示例:

    public void Main()
    {
        var names = new string[] { "andy", "lisa", "zoro", "billy" };
        var result = FilterBetween(names, 'a', 'e');
    }
    public IEnumerable<string> FilterBetween(IEnumerable<string> names, char start, char end)
    {
        return names.
            Where(name => name.
                First().
                Between(start, end));
    }

public static class ExtensionMethods
{
    public static bool Between<T>(this T actual, T lower, T upper) where T : IComparable<T>
    {
        return actual.CompareTo(lower) >= 0 && actual.CompareTo(upper) <= 0;
    }
}