使用JavaScript实现王室名称排序的技术问询
Hey there! Your initial approach of converting Roman numerals to integers is totally on the right track—chances are the issue was either in how you split the royal names or a bug in the Roman-to-integer conversion logic (like not handling subtractive cases like IX=9 instead of 11). Let's walk through a solid, working solution step by step.
The core requirement is a custom sort: first sort by the royal title (King/Queen) alphabetically, then by the numeric value of the Roman numeral suffix when titles match. Here's how to implement this:
Step 1: Reliable Roman Numeral to Integer Conversion
First, we need a function that correctly converts Roman numerals to integers, including subtractive combinations (IV=4, IX=9, XL=40, etc.). This is the most common pitfall—if your earlier function didn't handle these cases, that's probably why sorting failed.
Step 2: Custom Sort Key
For each royal name, we'll:
- Clean up any extra punctuation (like trailing commas in your example)
- Split the name into the title (e.g., "King") and Roman numeral (e.g., "III")
- Use a sort key that first compares the title (case-insensitively) and then the converted integer value of the numeral
Python Implementation
def roman_to_int(roman): roman_map = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} total = 0 prev_value = 0 # Iterate from right to left to handle subtractive cases for char in reversed(roman): current_value = roman_map[char] if current_value < prev_value: total -= current_value else: total += current_value prev_value = current_value return total def sort_royal_names(names): def sort_key(name): # Clean up trailing commas and whitespace cleaned_name = name.strip().rstrip(',') title, roman = cleaned_name.split() # Return a tuple: (lowercase title for case-insensitive sort, numeric value) return (title.lower(), roman_to_int(roman)) # Sort using our custom key return sorted(names, key=sort_key) # Test with your example input_names = ["King III,", "King II", "Queen IX"] sorted_result = sort_royal_names(input_names) print(sorted_result) # Output: ['King II', 'King III,', 'Queen IX']
JavaScript Implementation
If you're working in JS, here's an equivalent version:
function romanToInt(roman) { const romanMap = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}; let total = 0; let prevValue = 0; for (let i = roman.length - 1; i >= 0; i--) { const currentValue = romanMap[roman[i]]; if (currentValue < prevValue) { total -= currentValue; } else { total += currentValue; } prevValue = currentValue; } return total; } function sortRoyalNames(names) { return names.sort((a, b) => { // Clean up each name const cleanA = a.trim().replace(/,$/, ''); const cleanB = b.trim().replace(/,$/, ''); const [titleA, romanA] = cleanA.split(' '); const [titleB, romanB] = cleanB.split(' '); // Compare titles first (case-insensitive) const titleComparison = titleA.toLowerCase().localeCompare(titleB.toLowerCase()); if (titleComparison !== 0) { return titleComparison; } // If titles match, compare numeric values of Roman numerals return romanToInt(romanA) - romanToInt(romanB); }); } // Test example const inputNames = ["King III,", "King II", "Queen IX"]; const sortedResult = sortRoyalNames(inputNames); console.log(sortedResult); // Output: ['King II', 'King III,', 'Queen IX']
Why This Works
- The
roman_to_intfunction correctly handles all standard Roman numeral rules by iterating from right to left, subtracting smaller values when they precede larger ones. - The custom sort key ensures we first sort alphabetically by title (ignoring case, so "king" and "King" are treated the same), then by the numeric value of the suffix when titles are identical.
- We clean up extra punctuation to avoid issues with inconsistent input formatting (like trailing commas in your example).
内容的提问来源于stack exchange,提问作者Sai

