通过 Linq 找到给定对象的 2 个邻居
本文关键字:邻居 对象 Linq 通过 | 更新日期: 2023-09-27 17:57:02
我有一个对象列表,例如,
List<Person> list = new List<Person>
{
new Person { Name = "John", Age = 24 },
new Person { Name = "Tom", Age = 35 },
new Person { Name = "Mike", Age = 42 },
new Person { Name = "Steve", Age = 51 }
}
还有一个人,说{Phil, 45}
.
我想在列表中找到我们的 2 个人,这使得给定人的年龄介于他们之间。在我们的例子中,他们是迈克和史蒂夫。
我可以使用内置的 Linq 扩展执行此操作吗?
如果您愿意在两次迭代中执行此操作,则
很容易做到这一点:var sortedList = list.OrderBy(p => p.Age); // Only if not already sorted
var searchPerson = new Person { Name = "Phil", Age = 45 };
var prevPerson = sortedList.LastOrDefault(p => p.Age < searchPerson.Age);
var nextPerson = sortedList.FirstOrDefault(p => p.Age > searchPerson.Age);
但是,我必须告诉您,这真的不是 Linq 扩展的工作。 忘掉林克吧。
如果您确实有问题中指定的List<T>
,那么您可以使用List<T>.BinarySearch
方法。 如果您正在处理纯(不可索引)IEnumerable<T>
实例,则只需迭代它:
Person searchPerson = ...
Person previousPerson = null;
Person nextPerson = null;
foreach (var p in list.OrderBy(p => p.Age))
{
if (p.Age < searchPerson.Age)
previousPerson = p;
else
{
nextPerson = p;
break;
}
}
这将在一次迭代中获得结果,并且只扫描年龄较高的第一个Person
序列,而不是扫描到最后。
效率不是很高,但你可以做到
var orderedList = list.OrderBy(p => p.Age);
var neighbors = new List<Person>
{orderedList .FirstOrDefault(p => p.Age > phil.Age),
orderedList.LastOrDefault(p => p.Age < phil.Age)};
我会做这样的事情:
Person p = new Person("Phil", 45);
List<Person> sList = (from Person x in list orderby x.Age - p.Age select x).ToList();
for(int i = 0; i < sList.Count - 1; i++) {
if(sList[i] < 0 && sList[i + 1] > 0) {
// Found the two people - the person's age is between sList[i] and sList[i + 1]
break;
}
}
class Program
{
static void Main()
{
List<Person> persons = new List<Person>
{
new Person {Name = "John", Age = 24},
new Person {Name = "Tom", Age = 35},
new Person {Name = "Mike", Age = 42},
new Person {Name = "Steve", Age = 51}
};
//{Phil, 45}
persons.Between(age: 45);
}
}
public static class AgeExtensionMethod
{
public static Person[] Between(this List<Person> person,int age)
{
var orderdList = person.OrderBy(p => p.Age);
var k = orderdList.Where(p => p.Age < age).Last();
var s = orderdList.Where(p => p.Age > age).First();
return new[] {k, s};
}
}
不确定这是否是更好的方法。
乱,但都是linq:
class Person {
public string Name { get; set; }
public int Age { get; set; }
public override string ToString() {
return string.Format("{0} {1}", Name, Age);
}
}
class Program {
static void Main(string[] args) {
List<Person> list = new List<Person>
{
new Person { Name = "John", Age = 24 },
new Person { Name = "Tom", Age = 35 },
new Person { Name = "Mike", Age = 42 },
new Person { Name = "Steve", Age = 51 }
};
var phil = new Person { Name = "Phil", Age = 45 };
var findTwo = list.OrderBy(p => p.Age).Reverse().SkipWhile(p => p.Age > phil.Age).Take(1).Concat(list.OrderBy(p => p.Age).SkipWhile(p => p.Age < phil.Age).Take(1));
foreach(var person in findTwo) {
Console.WriteLine(person);
}
Console.WriteLine("DONE");
Console.ReadLine();
}
}
或
List<Person> list = new List<Person>
{
new Person { Name = "John", Age = 24 },
new Person { Name = "Tom", Age = 35 },
new Person { Name = "Mike", Age = 42 },
new Person { Name = "Steve", Age = 51 }
};
var phil = new Person { Name = "Phil", Age = 45 };
var twoNearest = from p2 in
(from p1 in list
where p1.Age > phil.Age || p1.Age < phil.Age
select new {
Name = p1.Name,
Age = p1.Age,
Younger = p1.Age < phil.Age
})
group p2 by p2.Younger into split
from p in split
where (p.Age == split.Max(a => a.Age) && p.Younger) || (p.Age == split.Min(a => a.Age) && !p.Younger)
select new Person {
Name = p.Name,
Age = p.Age,
};