我有一个自定义优先级数组。
int[] priorities = { 866, 663, 855, 853, 854};
我现在要使用此代码对列表进行排序,并根据标准选择第一个。
var target = (from people in GetNearbyPeopleList()
where people.DistanceToTravel > 0 && people.ReachedDestination == false
orderby //not sure what to do here
select people).FirstOrDefault();
所以我想按照我的自定义优先顺序排序。其中people.currentlocation由我的优先级数组排序。
我该做什么 - ?
orderby priorities.Contains(people.currentlocation)
这就是我能想到的全部,但它并没有按照我的自定义优先顺序排列。我希望它完全遵循这个顺序:
int[] priorities = { 866, 663, 855, 853, 854};
因此,如果位置是866,请选择那个。我只想选择一个,我想根据该优先级列表选择第一个。如果currentlocation == 866不存在,则选择663等等。
答案 0 :(得分:1)
如果你的值在编译时是固定的......避免使用数组并写:
orderby
people.currentLocation == 866 ? 1 :
people.currentLocation == 663 ? 2 :
people.currentLocation == 855 ? 3 :
people.currentLocation == 853 ? 4 :
people.currentLocation == 854 ? 5 :
6
如果您的值在运行时更改,但值的数量有一些固定的最大值,则写入:
Person FindPriorityPerson(IQueryable<Person> query,
int p1 = 0, int p2 = 0, int p3 = 0, int p4 = 0,
int p5 = 0, int p6 = 0, int p7 = 0, int p8 = 0)
{
return query.OrderBy(person =>
person.currentLocation == p1 ? 1 :
person.currentLocation == p2 ? 2 :
person.currentLocation == p3 ? 3 :
person.currentLocation == p4 ? 4 :
person.currentLocation == p5 ? 5 :
person.currentLocation == p6 ? 6 :
person.currentLocation == p7 ? 7 :
person.currentLocation == p8 ? 8 :
9).FirstOrDefault();
}
答案 1 :(得分:0)
我认为这样做会。这使您可以根据数组顺序进行排序。
必须添加逻辑,所以-1(未找到)在最后
CREATE TABLE movie(
id INT(1) NOT NULL AUTO_INCREMENT,
nearname VARCHAR(25) NOT NULL,
release_date DATE NOT NULL,
lang VARCHAR(10) NOT NULL,
PRIMARY KEY(id),
CONSTRAINT same_movie FOREIGN KEY(id) REFERENCES movie_cast(movie_id)
);
CREATE TABLE movie_cast(
movie_id INT(1) NOT NULL AUTO_INCREMENT,
director_name VARCHAR(20) NOT NULL,
actor_name VARCHAR(20) NOT NULL,
actress_name VARCHAR(20) NOT NULL,
PRIMARY KEY(movie_id),
CONSTRAINT same_movie FOREIGN KEY(movie_id) REFERENCES movie(id)
);
答案 2 :(得分:0)
这不可能通过这种方式完成。 * Linq无法以您需要的方式使用您自己的阵列。但是我可以想到其他几种方法
Contains
并查询所有项目,在客户端上选择第一项。 Contains
可以使用您自己的数组,但请注意它将其转换为参数,一个值表示一个参数。如果数组中的项目太多(> 100),请不要使用它,否则查询会很慢,并且会因超过约2000项而崩溃(取决于服务器类型)。* Amy B发现了一种方式,我很糟糕。但要注意限制。它不是每个值都使用一个,而是两个参数,使其更加受限制。它可能会导致表扫描,这可能会更昂贵,取决于表大小和数组大小。在20M表上,它需要大约25000倍的数据库资源,而不仅仅是使用Contains查询所有5行。您应该将它与Contains过滤器结合使用以避免表扫描,但这意味着每个项目有三个参数......
答案 3 :(得分:0)
Ctznkan525's回答让我想到了使用"Select with index"按顺序或优先顺序对数组进行排序。
所以你希望所有优先考虑的人都在列表或优先级中。第二个是列表中第二个被提及的优先级的人,第三个是列表中优先级为第三的人等。
您是否注意到我提到了识别订单的索引?因此,如果我将索引添加到您的优先级列表中,我可以按此索引进行排序。
如果GetNearByPeopleList返回IEnumerable,则此方法有效。
var indexedPriorities = priorities.Select( (priority, index) => new
{
Priority = priority,
OrderIndex = index,
});
var result = GetNearbyPeopleList()
.Where(...) // take only people you want
.Join(indexedPriorities, // join with indexedPriorities
people => people.CurrentLocation, // from each people take the CurrentLocation
indexedPrio => indexedPrio.Priority, // from each indexedPriority take the priority
(people, prio) => new // when they match, make a new object
{
Index = prio.Index, // containing the index of the matching priority
People = people, // and the matching data
})
.OrderBy(item => item.Index) // order by ascending index
.Select(item => item.People); // keep only the People
此代码不包含CurrentLocation中不在您的优先级列表中的所有人。如果你想要它们,你应该把它们Concat到你想要的地方,可能最后。
唉,linq-to-entities does not support "select with index"。您可以尝试先添加索引,将列表设为AsQueryable,然后执行join:
var indexedPriorities = = priorities.Select( (priority, index) => new
{
Priority = priority,
OrderIndex = index,
})
.AsQueryable();
var result = GetNearbyPeopleList()
.Where(...)
.Join(indexedPriorities,
people => people.CurrentLocation, CurrentLocation
indexedPrio => indexedPrio.Priority,
...
唉这不起作用,因为你只能传输简单类型AsQueryable以用于连接。
但是,如果数据是远程的,并且您确实需要这个,那么您可以将优先级和索引作为小数转移:
var indexedPriorities = = priorities.Select( (x, i) => (decimal)x + (decimal)i/1000M)
.AsQueryable();
小数点前的数字是优先级,小数点后是排序索引:(。001之前是.002等
IQueryable<People> nearbyPeople = GetNearbyPeopleList()
.Where(...);
var result = nearbyPeople.Join(indexedPriorities,
people => people.CurrentLocation,
prio => (int)Math.Floor(prio),
(people, prio) => new
{
OrderIndex =(prio - Math.Truncate(prio),
People = people,
})
.OrderBy(item => item.OrderIndex)
.Select(item => item.People);
首先,我将原始优先级列表:{866,663,855,853,854}更改为{866.000,663.001,855.002,853.003等}。假设您的优先级列表没有1000个元素。
然后我使用866.000,663.001等Math.Floor进行连接。匹配时,我将小数点后的部分保存为OrderIndex:.000,.001,.002等(不需要,但如果需要:乘以1000)
订购后我摆脱了OrderIndex。