mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-01-23 15:13:22 +01:00
Replace AlphanumericComparator with new CompareOptions.NumericOrdering
This commit is contained in:
parent
1ba8e2c93c
commit
098e8c6fed
5 changed files with 18 additions and 153 deletions
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
|
@ -136,19 +137,27 @@ namespace Emby.Naming.Video
|
|||
|
||||
if (videos.Count > 1)
|
||||
{
|
||||
var groups = videos.GroupBy(x => ResolutionRegex().IsMatch(x.Files[0].FileNameWithoutExtension)).ToList();
|
||||
var groups = videos
|
||||
.Select(x => (filename: x.Files[0].FileNameWithoutExtension.ToString(), value: x))
|
||||
.Select(x => (x.filename, resolutionMatch: ResolutionRegex().Match(x.filename), x.value))
|
||||
.GroupBy(x => x.resolutionMatch.Success)
|
||||
.ToList();
|
||||
|
||||
videos.Clear();
|
||||
|
||||
StringComparer comparer = StringComparer.Create(CultureInfo.InvariantCulture, CompareOptions.NumericOrdering);
|
||||
foreach (var group in groups)
|
||||
{
|
||||
if (group.Key)
|
||||
{
|
||||
videos.InsertRange(0, group
|
||||
.OrderByDescending(x => ResolutionRegex().Match(x.Files[0].FileNameWithoutExtension.ToString()).Value, new AlphanumericComparator())
|
||||
.ThenBy(x => x.Files[0].FileNameWithoutExtension.ToString(), new AlphanumericComparator()));
|
||||
.OrderByDescending(x => x.resolutionMatch.Value, comparer)
|
||||
.ThenBy(x => x.filename, comparer)
|
||||
.Select(x => x.value));
|
||||
}
|
||||
else
|
||||
{
|
||||
videos.AddRange(group.OrderBy(x => x.Files[0].FileNameWithoutExtension.ToString(), new AlphanumericComparator()));
|
||||
videos.AddRange(group.OrderBy(x => x.filename, comparer).Select(x => x.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace Emby.Server.Implementations.Sorting
|
||||
{
|
||||
|
|
@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.Sorting
|
|||
ArgumentNullException.ThrowIfNull(x);
|
||||
ArgumentNullException.ThrowIfNull(y);
|
||||
|
||||
return AlphanumericComparator.CompareValues(x.Studios.FirstOrDefault(), y.Studios.FirstOrDefault());
|
||||
return CultureInfo.InvariantCulture.CompareInfo.Compare(x.Studios.FirstOrDefault(), y.Studios.FirstOrDefault(), CompareOptions.NumericOrdering);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Jellyfin.Extensions;
|
||||
|
||||
|
|
@ -9,7 +11,7 @@ namespace MediaBrowser.Controller.Sorting
|
|||
{
|
||||
public static class SortExtensions
|
||||
{
|
||||
private static readonly AlphanumericComparator _comparer = new AlphanumericComparator();
|
||||
private static readonly StringComparer _comparer = StringComparer.Create(CultureInfo.InvariantCulture, CompareOptions.NumericOrdering);
|
||||
|
||||
public static IEnumerable<T> OrderByString<T>(this IEnumerable<T> list, Func<T, string> getName)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Jellyfin.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Alphanumeric <see cref="IComparer{T}" />.
|
||||
/// </summary>
|
||||
public class AlphanumericComparator : IComparer<string?>
|
||||
{
|
||||
/// <summary>
|
||||
/// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
|
||||
/// </summary>
|
||||
/// <param name="s1">The first object to compare.</param>
|
||||
/// <param name="s2">The second object to compare.</param>
|
||||
/// <returns>A signed integer that indicates the relative values of <c>x</c> and <c>y</c>.</returns>
|
||||
public static int CompareValues(string? s1, string? s2)
|
||||
{
|
||||
if (s1 is null && s2 is null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s1 is null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s2 is null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int len1 = s1.Length;
|
||||
int len2 = s2.Length;
|
||||
|
||||
// Early return for empty strings
|
||||
if (len1 == 0 && len2 == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len1 == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len2 == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pos1 = 0;
|
||||
int pos2 = 0;
|
||||
|
||||
do
|
||||
{
|
||||
int start1 = pos1;
|
||||
int start2 = pos2;
|
||||
|
||||
bool isNum1 = char.IsDigit(s1[pos1++]);
|
||||
bool isNum2 = char.IsDigit(s2[pos2++]);
|
||||
|
||||
while (pos1 < len1 && char.IsDigit(s1[pos1]) == isNum1)
|
||||
{
|
||||
pos1++;
|
||||
}
|
||||
|
||||
while (pos2 < len2 && char.IsDigit(s2[pos2]) == isNum2)
|
||||
{
|
||||
pos2++;
|
||||
}
|
||||
|
||||
var span1 = s1.AsSpan(start1, pos1 - start1);
|
||||
var span2 = s2.AsSpan(start2, pos2 - start2);
|
||||
|
||||
if (isNum1 && isNum2)
|
||||
{
|
||||
// Trim leading zeros so we can compare the length
|
||||
// of the strings to find the largest number
|
||||
span1 = span1.TrimStart('0');
|
||||
span2 = span2.TrimStart('0');
|
||||
var span1Len = span1.Length;
|
||||
var span2Len = span2.Length;
|
||||
if (span1Len < span2Len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (span1Len > span2Len)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int result = span1.CompareTo(span2, StringComparison.InvariantCulture);
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
} while (pos1 < len1 && pos2 < len2);
|
||||
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Compare(string? x, string? y)
|
||||
{
|
||||
return CompareValues(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Extensions.Tests
|
||||
{
|
||||
public class AlphanumericComparatorTests
|
||||
{
|
||||
// InlineData is pre-sorted
|
||||
[Theory]
|
||||
[InlineData(null, "", "1", "9", "10", "a", "z")]
|
||||
[InlineData("50F", "100F", "SR9", "SR100")]
|
||||
[InlineData("image-1.jpg", "image-02.jpg", "image-4.jpg", "image-9.jpg", "image-10.jpg", "image-11.jpg", "image-22.jpg")]
|
||||
[InlineData("Hard drive 2GB", "Hard drive 20GB")]
|
||||
[InlineData("b", "e", "è", "ě", "f", "g", "k")]
|
||||
[InlineData("123456789", "123456789a", "abc", "abcd")]
|
||||
[InlineData("12345678912345678912345678913234567891", "123456789123456789123456789132345678912")]
|
||||
[InlineData("12345678912345678912345678913234567891", "12345678912345678912345678913234567891")]
|
||||
[InlineData("12345678912345678912345678913234567891", "12345678912345678912345678913234567892")]
|
||||
[InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891a")]
|
||||
[InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891b")]
|
||||
[InlineData("a5", "a11")]
|
||||
[InlineData("a05a", "a5b")]
|
||||
[InlineData("a5a", "a05b")]
|
||||
[InlineData("6xxx", "007asdf")]
|
||||
[InlineData("00042Q", "42s")]
|
||||
public void AlphanumericComparatorTest(params string?[] strings)
|
||||
{
|
||||
var copy = strings.Reverse().ToArray();
|
||||
Array.Sort(copy, new AlphanumericComparator());
|
||||
Assert.Equal(strings, copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue