使用Array作为Comparer覆盖LINQ查询中的默认排序

本文关键字:默认 排序 查询 LINQ Array 作为 Comparer 覆盖 使用 | 更新日期: 2023-09-27 18:25:15

我有一个ID号列表,我从会话变量中提取这些ID号,并将其转换为数组,用于LINQ查询,然后用于填充下拉列表。这基本上是程序访问过的最近客户端的列表。我希望它能按上次访问的顺序显示它们。

示例数组值(66、78、55、24、80)

在LINQ查询之后,默认情况下,它按ID排序:(24,55,66,78,80)

因此,当它显示在dropdownlist中时,它是这样排序的,而我真正需要的只是它保持在数组值的顺序中,只是相反:(80,24,55,78,66)

代码:

// Grab pre-built session variable with comma delimited int values
string RecentClients = Session["RecentClients"].ToString();
// Convert to Array
int[] RecentClientsArray = 
Array.ConvertAll(RecentClients.Split(','), n => Convert.ToInt32(n));
// Display in gridview to see current order of array (For debug purposes)
gridArray.DataSource = RecentClientsArray;
gridArray.DataBind();
// Setup LINQ
DataClasses1DataContext db = new DataClasses1DataContext();
// Populate RecenClientList using RecentClientsArray to compare to ConsumerID
var RecentClientList = 
(from c in db.ClientNames
 where RecentClientsArray.Contains(c.ConsumerID)
 select new { FullName = c.LastName + ", " + c.FirstName + " #" + c.ConsumerID, 
              recentConsumerID = c.ConsumerID});

// Display in gridview to see new order after populating var RecentClientList 
// (for debug purposes)
gridList.DataSource = RecentClientList;
gridList.DataBind();
// Set and bind values for dropdown list.
ddLastClients.DataSource = RecentClientList;
ddLastClients.DataTextField = "FullName";
ddLastClients.DataValueField = "recentConsumerID";
ddLastClients.DataBind();

使用公认的解决方案编辑已更正的代码:

// Grab pre-built session variable with comma delimited int values
string RecentClients = Session["RecentClients"].ToString();
// Convert to Array
int[] RecentClientsArray = Array.ConvertAll(RecentClients.Split(','), n => Convert.ToInt32(n));
// Setup LINQ
DataClasses1DataContext db = new DataClasses1DataContext();
// Populate RecenClientList using RecentClientsArray to compare to ConsumerID
var RecentClientList = (from c in db.ClientNames
                        where RecentClientsArray.Contains(c.ConsumerID)
                        select new { FullName = c.LastName + ", " + c.FirstName + " #" + c.ConsumerID, recentConsumerID = c.ConsumerID });
var clients = (from item in RecentClientsArray
                join client in RecentClientList.ToList()
                on item equals client.recentConsumerID
                select client).Reverse().Distinct();
// Set and bind values for dropdown list.
ddLastClients.DataSource = clients;
ddLastClients.DataTextField = "FullName";
ddLastClients.DataValueField = "recentConsumerID";
ddLastClients.DataBind();

使用Array作为Comparer覆盖LINQ查询中的默认排序

我会按照您当时写的那样留下您的查询,然后在内存中处理排序。

给定

var RecentClientsArray = ...
var RecentClientList = ...

您可以使用Enumerable.Join将这些集合在一起。CCD_ 2具有在联接运算中保持序列顺序的性质。使用join来获得基于数组的初始订单,然后使用Reverse来满足您需求的最后部分。所以你可能只是有

var clients = 
    (from item in RecentClientsArray 
     join client in RecentClientList.ToList() // materialize result from db
     on item equals client.recentConsumerID
     select client).Reverse();

您应该以数组的相反顺序看到clients,然后将其用作控件上的数据源。

我认为您需要使用OrderBy(Func<>,IComparer<>)并指定您自己的Comparer,它将实现您的(直接从stackoverflow复制,抱歉)。。。目前还没有实现它的优雅解决方案,tho

请尝试以下操作,我使用List<int>是因为我需要访问IndexOf,我在LINQ查询的added orderby子句中使用它:

       List<int> RecentClientsArray = Array.ConvertAll(RecentClients.Split(','), n => Convert.ToInt32(n)).ToList();
       // other code
       var RecentClientList = (from c in db.ClientNames
                               where RecentClientsArray.Contains(c.ConsumerID)
                               orderby RecentClientsArray.IndexOf(c.ConsumerID) descending
                               select new { FullName = c.LastName + ", " + c.FirstName + " #" + c.ConsumerID, recentConsumerID = c.HorizonID });

我的解决方案:使用字典和反向数组项

这是我的代码:

            // Grab pre-built session variable with comma delimited int values
            string RecentClients = Session["RecentClients"].ToString();
            // Convert to Array
            int[] RecentClientsArray = Array.ConvertAll(RecentClients.Split(','), n => Convert.ToInt32(n));

            //NEW- I use dictionary to get the right place in reverse
            int ind = 0;
            Dictionary<int, int> dic = new Dictionary<int, int>();
            foreach (var item in RecentClientsArray.Reverse())
            {
                dic.Add(item, ind);
                ind++;
            }

            // Display in gridview to see current order of array (For debug purposes)
            gridArray.DataSource = RecentClientsArray;
            gridArray.DataBind();
            // Setup LINQ
            DataClasses1DataContext db = new DataClasses1DataContext();
            // Populate RecenClientList using RecentClientsArray to compare to ConsumerID
            //NEW- use orderby with dictionary
            var RecentClientList = (from c in db.ClientNames
            where RecentClientsArray.Contains(c.ConsumerID)
            orderby dic[c.ConsumerID]
            select new { FullName = c.LastName + ", " + c.FirstName + " #" + c.ConsumerID, recentConsumerID = c.HorizonID, ID = c.ConsumerID });
            // Display in gridview to see new order after populating var RecentClientList (for debug purposes)
            gridList.DataSource = RecentClientList;
            gridList.DataBind();
            // Set and bind values for dropdown list.
            ddLastClients.DataSource = RecentClientList;
            ddLastClients.DataTextField = "FullName";
            ddLastClients.DataValueField = "recentConsumerID";
            ddLastClients.DataBind();           



祝你好运,