Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于自定义优先级的对象排序和选择_C#_Linq_Sql Order By - Fatal编程技术网

C# 基于自定义优先级的对象排序和选择

C# 基于自定义优先级的对象排序和选择,c#,linq,sql-order-by,C#,Linq,Sql Order By,我有一个自定义优先级数组 int[] priorities = { 866, 663, 855, 853, 854}; 我现在有这个代码来对我的列表进行排序,并根据标准选择第一个 var target = (from people in GetNearbyPeopleList() where people.DistanceToTravel > 0 && people.ReachedDestinat

我有一个自定义优先级数组

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,依此类推。

我认为这样就可以了。这将根据数组顺序进行排序

不得不添加逻辑,因此-1(未找到)位于末尾

orderby Array.IndexOf(priorities, people.currentLocation) == -1 ? Integer.MaxValue : Array.IndexOf(priorities, people.currentLocation);
这不能这样做。*Linq不能以您需要的方式使用您自己的阵列。但我可以想到其他几种方法

  • 重新设计应用程序,以便在服务器上的表中具有优先级
  • 使用表值参数(TVP)。这是将数组发送到服务器以便在查询中使用的正确方法,它可以扩展到数千项而不会出现问题。它需要支持该功能的服务器(如Microsoft SQL server),并且查询必须在linq之外完成。Linq不支持这一点
  • 使用
    包含
    并查询所有项目,在客户端选择第一个项目<代码>包含
    可以使用您自己的数组,但是请注意,它将其转换为参数,一个值表示一个参数。如果阵列中的项目太多(>100),请不要使用它,否则查询速度会很慢,并且会崩溃约2000个项目(取决于服务器类型)
  • 循环数组并一次查询一项。例如,您可以将它与Contains结合起来,一次查询10个项目,以提高速度

*艾米B找到了一条路,我的错。但要注意这些限制。它不是每个值使用一个参数,而是每个值使用两个参数,这使得它更受约束。它可能会导致表扫描,而表扫描的成本可能要高得多,这取决于表大小和数组大小。在20M表上,它需要大约250000倍的数据库资源,而不仅仅是用Contains查询所有5行。您可能应该将它与Contains过滤器结合起来以避免表扫描,但这意味着每个项有三个参数…

如果您的值在编译时是固定的。。。避免使用数组并写入:

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();
}
Person FindPriorityPerson(IQueryable查询,
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();
}
answer给了我一个想法,可以用来按顺序或优先级对数组进行排序

所以你希望所有人都有优先权,排在第一位。第二位是名单中第二位提到的具有优先权的人,第三位是名单中第三位的人,等等

你有没有注意到我提到了标识订单的索引?因此,如果我将索引添加到优先级列表中,我可以按此索引排序

如果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
此代码将删除所有当前位置不在您的优先级列表中的人员。如果你想要它们,你应该把它们放在你想要的地方,也许在最后

唉。您可以尝试首先添加索引,使列表可查询,然后执行连接:

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, 
    ...
唉,这是行不通的,因为您只能传输简单的类型,以便在联接中使用

但是,如果数据是远程的,并且您确实需要这样做,则可以将优先级和索引作为十进制数进行传输:

  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);
IQueryable nearbyPeople=GetNearbyPeopleList()
.其中(…);
var result=nearbyPeople.Join(indexedPriorities,
people=>people.CurrentLocation,
prio=>(int)数学楼层(prio),
(人物,prio)=>全新
{
OrderIndex=(prio-Math.Truncate(prio),
人=人,
})
.OrderBy(item=>item.OrderIndex)
.Select(item=>item.People);
首先,我将原始优先级列表:{866636585553854}更改为{866.000、663.001、855.002、853.003等}。假设优先级列表没有1000个元素

然后,我与数学楼层866.000、663.001等进行连接。匹配时,我将小数点后的部分保留为OrderIndex.000、001、002等(不需要,但如果需要:乘以1000)


排序后,我去掉了OrderIndex。

我得到了一个错误,“IndexOf”方法没有重载1个参数。将其更改为array.indexofSystem.NotSupportedException:method“Int32 IndexOf[Int32](Int32[],Int32)'不支持转换为SQLIf NEARYPEPLIST AsEnumerable或AsQueryable的结果?换句话说,此结果是由数据库执行的查询,还是本地内存中的一系列项?这对我来说失败,原因是:System.NotSupportedException:不支持返回自引用常量表达式的IQueryable。I tr我用Math.Truncate对这个方法进行了测试,结果很有效,可能这只是特定ORM的问题。我想知道生成的sql是什么样子的。