通过与linq的相似性对对象进行排序

时间:2016-11-03 12:05:21

标签: c# linq sorting

我创建了一个程序,它根据排序的ObjectProperties列表处理数据,其中一个属性是字符串列表。现在,可以根据大小和速率等简单属性对元素进行排序,但我希望能够按字符串相似性列表对子顺序进行排序。换句话说,我想按大小排序,然后按速率排序,然后按字符串列表的相似性排序。

lMessages.OrderBy(x => x.Size).ThenBy(x => x.Rate).ThenBy(???)

我可以很容易地计算相似度:

private double FindExactMatrixSimilarity(List<string> A, List<string> B)
{
    var lSimilarity = A.Intersect(B);
    var lUnion = A.Union(B);

    if (lUnion.Count() == 0)
        return 0;
    else
        return Convert.ToDouble(lSimilarity.Count()) / Convert.ToDouble(lUnion.Count());
}

我不知道如何使用这些信息。看起来它需要一个初始条件。如果我知道第一个对象,我可以排序很好。它不是确定性的,但我不在乎。如果我想按大小排序,然后评分,然后是相似性,我认为我不知道哪个对象在我的小组中首先是大小和速率匹配的。我是不是太复杂了?

1 个答案:

答案 0 :(得分:1)

根据您的评论,当您根据具有相同大小和速率的每组消息中的第一个元素计算相似度时,我认为这种方式应该适用于您。它并不漂亮,它不是单一的Linq声明,但它应该有效。

我把它分成更多单个命令,而不是为了更好地理解所需的命令。

List<Message> finalList = new List<Message>();

// First, group all elements with similar size and rate
var groupedMessages = orderedMessages.GroupBy(m => new { m.Size, m.Rate });

// Now bring them into the correct order by their size and rate
groupedMessages = groupedMessages.OrderBy(gm => gm.Key.Rate).ThenBy(gm => gm.Key.Size);

// Now sort by similarity within each group
foreach (var gm in groupedMessages)
{
    List<string> baseStringList = gm.First().StringList;

    var orderedGroupEntries = gm.OrderByDescending(
        m => FindExactMatrixSimilarity(baseStringList, m.StringList));

    // This will add to the result list in the correct order
    finalList.AddRange(orderedGroupEntries);
}

编辑:这是一个仅限LINQ的版本:

var result = (from m in messageList
              group m by new
              {
                  m.Rate,
                  m.Size
              } into groupedMessages
              orderby groupedMessages.Key.Rate, groupedMessages.Key.Size
              select new List<Message>(
                  from m in groupedMessages
                  let baseStringList = groupedMessages.First().StringList
                  orderby FindExactMatrixSimilarity(baseStringList, m.StringList) descending
                  select m)
              ).SelectMany(m => m);