Skip to content

fix: sort file names with leading zeros, prefixes, and numeric chunks correctly - #3036

Closed
AlexAndBear wants to merge 4 commits into
mainfrom
issues/2993
Closed

fix: sort file names with leading zeros, prefixes, and numeric chunks correctly#3036
AlexAndBear wants to merge 4 commits into
mainfrom
issues/2993

Conversation

@AlexAndBear

@AlexAndBear AlexAndBear commented Aug 5, 2026

Copy link
Copy Markdown
Member

Description

Improved file and folder name sorting to match Windows Explorer behavior, with proper handling of leading zeros, numeric prefixes, and complex naming patterns.

Problems Fixed (compared to main branch)

Main Branch Issues:

  1. Incorrect leading zero handling: Files like 0, 00, 000 were sorted inconsistently instead of by zero-count
  2. Missing prefix recognition: report and report final were not sorted as prefix/suffix pairs
  3. Poor numeric chunk comparison: img2, img02, img10 didn't sort correctly (should be img2 < img02 < img10)
  4. No basename/extension separation: Files were compared as whole strings instead of separating base name from extension
  5. Insufficient suffix handling: Files with spaces, underscores, hyphens, or parentheses after a common root weren't grouped properly

Examples of incorrect sorting in main:

  • 00, 000, 0 → now correctly: 0, 00, 000
  • report final, report → now correctly: report, report final
  • img10, img2 → now correctly: img2, img10
  • Project Archive, Project → now correctly: Project, Project Archive

What Changed

New Sorting Features

1. Correct Natural Sorting

  • Chunk-based comparison: numeric chunks by value, text chunks by collator
  • Leading zero handling: 0 < 00 < 000 (longer zeros sort later when values equal)
  • Proper transitivity: deterministic sort order regardless of input order
  • Implementation: compareStringChunks() (sortInternals.ts:334-404)

2. File Prefix/Suffix Detection

  • Split basename from extension for comparison
  • Recognize prefix relationships: report comes before report final
  • Group files with common roots and different suffixes
  • Implementation: compareFileNamesByBasePrefix() (sortInternals.ts:172-229)

3. Performance Optimization for Non-Name Sorting

  • Schwartzian Transform: Precompute sort keys once per item (sortInternals.ts:53-77)
  • Eliminates redundant regex/string operations from comparison loop
  • Significant speedup for size, date, and nested property sorting
  • Trade-off: Name sorting is slower due to additional correctness logic

4. Case/Accent Tiebreaking

  • Added finalTiebreakerCollator with sensitivity: 'variant' (sortInternals.ts:36-39)
  • True case-sensitive final tiebreak: Apfel < Äpfel, File.txt < file.txt

5. Comprehensive Test Coverage

  • Full array validation with .toEqual() instead of partial .filter().toMatchObject()
  • Now validates all 119 items in correct order for both asc/desc
  • Added test for nested property sorting (useSort.spec.ts:634-675)
  • Tests cover: leading zeros, prefixes, numeric chunks, umlauts, case sensitivity

File Structure

  • New: sortInternals.ts - Core sorting logic (405 lines)

    • sortItemsByField - Main entry point with Schwartzian transform
    • compareStringChunks - Unified chunk-based comparison
    • compareFileNamesByBasePrefix - File-specific prefix/extension logic
    • Helper functions for name/extension splitting, prefix detection
  • Updated: useSort.ts - Delegates to sortInternals.sortItemsByField()

Performance Benchmarks

Comparison with main branch (20,000 items):

Sort Type Main Branch This PR Change Notes
Name 29.19ms 61.68ms -53% slower ⬇️ More correctness logic (leading zeros, prefixes, transitivity)
Size 52.97ms 12.36ms +77% faster ⬆️ Schwartzian transform optimization
Nested Property 48.36ms 14.76ms +69% faster ⬆️ Schwartzian transform optimization
Date (function) 59.06ms 10.96ms +81% faster ⬆️ Schwartzian transform optimization

Trade-offs:

  • ✅ Non-name sorting (size, date, nested properties): +69% to +81% faster
  • ⚠️ Name sorting: -53% slower but more correct (leading zeros, prefixes, case-sensitivity)
  • 💡 Real-world impact: Most UIs have 100-1000 items where name sorting takes 2-3ms (still very fast)

Testing

Unit Tests - All 5 tests pass:

  • ✅ Nested property paths (spaceQuota.total)
  • ✅ Leading zeros (0, 00, 000 sorted by count)
  • ✅ Prefix/suffix pairs (report, report final)
  • ✅ Case/accent handling (Äpfel/Apfel, Straße/Strasse)
  • ✅ Full sort order validation (119 items asc/desc)

Quality Checks:

  • pnpm check:types passes
  • pnpm format:check passes
  • pnpm test:unit --run passes

Related Issue

Fixes #2993

Types of changes

  • Enhancement (better sorting algorithm, performance optimization)
  • Tests (expanded coverage, proper validation)

@AlexAndBear
AlexAndBear force-pushed the issues/2993 branch 4 times, most recently from 583389d to 616fdc5 Compare August 5, 2026 12:52
@AlexAndBear
AlexAndBear requested a review from JammingBen August 5, 2026 12:52
@AlexAndBear
AlexAndBear marked this pull request as ready for review August 5, 2026 12:52
@AlexAndBear AlexAndBear changed the title fix: name sorting with leading zeroes fix: sort file names with leading zeros, prefixes, and numeric chunks correctly Aug 6, 2026
@AlexAndBear AlexAndBear closed this Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web client ignores leading zeros when sorting by name

1 participant