Как отсортировать объект в списке по неуникальному значению?

Я пытаюсь классифицировать статьи по сохраненным ключевым словам. У меня есть список ключевых слов для категории, и я хочу, чтобы статье была присвоена категория с наибольшим количеством ключевых слов.

For Each keyword As String In category.Keywords
    category.tempCount += Regex.Matches(article.Item("title").InnerXml, Regex.Escape(keyword)).Count
    category.tempCount += Regex.Matches(article.Item("description").InnerXml, Regex.Escape(keyword)).Count
Next

И это делается для каждой категории, запускаемой для каждой статьи. Я пытаюсь отсортировать список, чтобы определить, какая категория лучше всего подходит для этой статьи. Однако возможно, что более чем одна категория является лучшей, и ни одна из категорий не подходит. Так что запуск этого мне не помог:

Categories.Sort(
Function(article1 As ArticleCategory, article2 As ArticleCategory)
    Return article1.tempCount.CompareTo(article2.tempCount)
End Function)

Может быть, я делаю все это неправильно, но пока я думаю, что я на правильном пути. (У меня также есть сравнение по умолчанию в классе Category, просто оно тоже не работает.)

Я получаю исключение при сортировке, которая, скорее всего, вызвана тем, что они не уникальны.

Исключением, которое я получаю, является InvalidOperationException: не удалось сравнить два элемента в массиве. Это с помощью компаратора, который я построил в ArticleClass.

Imports System.Xml

Class ArticleCategory
Implements IComparer(Of ArticleCategory)

Public ReadOnly key As Int32
Public ReadOnly Name As String
Public ReadOnly Keywords As List(Of String)
Public tempCount As Integer = 0

Public Sub New(ByVal category As XmlElement)
    key = System.Web.HttpUtility.UrlDecode(category.Item("ckey").InnerXml)
    Name = System.Web.HttpUtility.UrlDecode(category.Item("name").InnerXml)

    Dim tKeywords As Array = System.Web.HttpUtility.UrlDecode(category.Item("keywords").InnerXml).Split(",")
    Dim nKeywords As New List(Of String)
    For Each keyword As String In tKeywords
        If Not keyword.Trim = "" Then
            nKeywords.Add(keyword.Trim)
        End If
    Next

    Keywords = nKeywords
End Sub

'This should be removed if your using my solution.
Public Function Compare(ByVal x As ArticleCategory, ByVal y As ArticleCategory) As Integer Implements System.Collections.Generic.IComparer(Of ArticleCategory).Compare
    Return String.Compare(x.tempCount, y.tempCount)
End Function


End Class

person JustinKaz    schedule 17.12.2011    source источник


Ответы (2)


Вам необходимо реализовать IComparable вместо IComparer.

IComparer будет реализован классом, выполняющим сортировку (например, класс List), а IComparable будет реализован сортируемым классом.

Например:

Public Function CompareTo(other As ArticleCategory) As Integer Implements System.IComparable(Of ArticleCategory).CompareTo
    Return Me.tempCount.CompareTo(other.tempCount)
End Function
person competent_tech    schedule 18.12.2011
comment
Это может сработать... хотя сейчас я использую LINQ для сортировки. Очень прост в использовании, нет необходимости использовать компаратор. - person JustinKaz; 19.12.2011

Лучшим решением, которое я нашел, было использование Microsoft LINQ (язык запросов для объектов), он работает очень хорошо и быстро дает правильный результат.

Dim bestCat As ArticleCategory
bestCat = (From cat In Categories
           Order By cat.tempCount Descending, cat.Name
           Select cat).First

Завершение моего решения:

For Each category As ArticleCategory In Categories
    category.tempCount = 0

    For Each keyword As String In category.Keywords
        category.tempCount += Regex.Matches(System.Web.HttpUtility.UrlDecode(article.Item("title").InnerXml), Regex.Escape(keyword)).Count
        category.tempCount += Regex.Matches(System.Web.HttpUtility.UrlDecode(article.Item("description").InnerXml), Regex.Escape(keyword)).Count
    Next

Next

Dim bestCat As ArticleCategory

Try
    bestCat = (From cat In Categories
               Order By cat.tempCount Descending, cat.Name
               Select cat).First
Catch ex As Exception
    ReportStatus(ex.Message)
End Try

Так что это мой предпочтительный метод для сортировки или запроса к объекту списка или массиву. Он дает наилучший результат за самое короткое время без необходимости добавления реализаций IComparer в ваш класс.

Ознакомьтесь с ним на Microsoft.com.

person JustinKaz    schedule 19.12.2011