按字典顺序排序字符串数组
Lexicographically Sort String Array
我一直在研究一个挑战并研究了几个小时,但仍然无法解决如何 "properly" 在 C# 中按字典顺序对字符串数组或字符串列表进行排序。
我正在挑战的问题:
- 只考虑两个字符串的小写字母。
- 比较它们以找出哪些字符出现在 两个 字符串中。
- 比较这些字符并找出哪个原始字符串包含每个字符的出现次数最多。
- 将结果作为字符串追加,其格式描述哪个字符串具有更高的计数“1:”或“2:”,或者如果等于“=:”,后跟该字符串中由“/”连接的所有字符".
- 将结果按长度降序排序,当它们长度相等时,将子字符串按字典序升序排序。
结果示例如下,下面是我的输出:
"2:eeeee/2:yy/=:hh/=:rr"
"2:eeeee/2:yy/=:rr/=:hh"
另一个正确结果的例子是下面是我的输出:
1:ooo/1:uuu/2:sss/=:nnn/1:ii/2:aa/2:dd/2:ee/=:gg
=:nnn/1:ooo/1:uuu/2:sss/=:gg/1:ii/2:aa/2:dd/2:ee
导致此问题的代码行是:
strings = strings.OrderByDescending(x => x.Length).ThenBy(c => c).ToArray();
我尝试了不同的方法来解决这个问题,例如将字符串拆分为特定长度的单个字符串数组,执行字典顺序,然后将它们追加到结果中。但是对于许多不同的测试用例,一个会通过而另一个会失败。
我的问题是找出为什么 C# 将“=”视为小于数字,而实际上它在 ASCII 图表上更大。我 运行 进行了测试,这就是 String.Compare 给我的结果。在Python,它给了我一些不一样的东西。
这是我的完整代码,欢迎指出任何错误。我只编程了 9 个月。我知道这不是最好的解决方案。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
string s1 = "looping is fun but dangerous";
string s2 = "less dangerous than coding";
// Expected
Console.WriteLine("1:ooo/1:uuu/2:sss/=:nnn/1:ii/2:aa/2:dd/2:ee/=:gg\n");
// Result
Console.WriteLine(StringsMix(s1, s2));
}
public static string StringsMix(string s1, string s2)
{
StringBuilder sb = new StringBuilder();
// Convert string to char arrays order by ascending
char[] s1Chars = s1.Where(x => char.IsLower(x)).OrderBy(x => x).ToArray();
char[] s2Chars = s2.Where(x => char.IsLower(x)).OrderBy(x => x).ToArray();
// Insert arrays to find characters that appear in both
char[] inter = s1Chars.Intersect(s2Chars).ToArray();
for (int i = 0; i < inter.Length; i++){
// For each character, put all occurences in their respective array
// Get count
char[] s1Ch = s1.Where(x => x.Equals(inter[i])).ToArray();
char[] s2Ch = s2.Where(x => x.Equals(inter[i])).ToArray();
int s1Count = s1Ch.Length;
int s2Count = s2Ch.Length;
if (s1Count > s2Count)
{
string chars = new String(s1Ch);
sb.Append("1:" + chars + "/");
}
else if (s2Count > s1Count)
{
string chars = new String(s2Ch);
sb.Append("2:" + chars + "/");
}
else if (s1Count == s2Count)
{
string chars = new String(s1Ch);
sb.Append("=:" + chars + "/");
}
}
string final = String.Empty;
string[] strings = sb.ToString().Split('/');
strings = strings.OrderByDescending(x => x.Length).ThenBy(c => c).ToArray(); // "Lexicographical ordering"
final = String.Join("/", strings);
strings = final.Split('/').Where(x => x.Length > 3).Select(x => x).ToArray(); // Remove trailing single characters
final = String.Join("/", strings);
return final;
}
}
}
发生这种情况是因为 '='
在 '1'
和 '2'
之前排序 ;您希望它在 个数字之后 排序。
你可以通过在中间添加特殊条件来强制执行此顺序:
var specialOrder = "12=";
var ordered = data
.OrderByDescending(s => s.Length)
.ThenBy(s => specialOrder.IndexOf(s[0])) // <<== Add this
.ThenBy(s => s);
这将确保初始字符按照specialOrder
字符串中字符的顺序排序,即'1'
,然后是'2'
,然后是'='
。
注意:代码假设序列没有空字符串。你的代码确保每个字符串至少有三个字符,所以这不是问题。
我一直在研究一个挑战并研究了几个小时,但仍然无法解决如何 "properly" 在 C# 中按字典顺序对字符串数组或字符串列表进行排序。
我正在挑战的问题:
- 只考虑两个字符串的小写字母。
- 比较它们以找出哪些字符出现在 两个 字符串中。
- 比较这些字符并找出哪个原始字符串包含每个字符的出现次数最多。
- 将结果作为字符串追加,其格式描述哪个字符串具有更高的计数“1:”或“2:”,或者如果等于“=:”,后跟该字符串中由“/”连接的所有字符".
- 将结果按长度降序排序,当它们长度相等时,将子字符串按字典序升序排序。
结果示例如下,下面是我的输出:
"2:eeeee/2:yy/=:hh/=:rr"
"2:eeeee/2:yy/=:rr/=:hh"
另一个正确结果的例子是下面是我的输出:
1:ooo/1:uuu/2:sss/=:nnn/1:ii/2:aa/2:dd/2:ee/=:gg
=:nnn/1:ooo/1:uuu/2:sss/=:gg/1:ii/2:aa/2:dd/2:ee
导致此问题的代码行是:
strings = strings.OrderByDescending(x => x.Length).ThenBy(c => c).ToArray();
我尝试了不同的方法来解决这个问题,例如将字符串拆分为特定长度的单个字符串数组,执行字典顺序,然后将它们追加到结果中。但是对于许多不同的测试用例,一个会通过而另一个会失败。
我的问题是找出为什么 C# 将“=”视为小于数字,而实际上它在 ASCII 图表上更大。我 运行 进行了测试,这就是 String.Compare 给我的结果。在Python,它给了我一些不一样的东西。
这是我的完整代码,欢迎指出任何错误。我只编程了 9 个月。我知道这不是最好的解决方案。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
string s1 = "looping is fun but dangerous";
string s2 = "less dangerous than coding";
// Expected
Console.WriteLine("1:ooo/1:uuu/2:sss/=:nnn/1:ii/2:aa/2:dd/2:ee/=:gg\n");
// Result
Console.WriteLine(StringsMix(s1, s2));
}
public static string StringsMix(string s1, string s2)
{
StringBuilder sb = new StringBuilder();
// Convert string to char arrays order by ascending
char[] s1Chars = s1.Where(x => char.IsLower(x)).OrderBy(x => x).ToArray();
char[] s2Chars = s2.Where(x => char.IsLower(x)).OrderBy(x => x).ToArray();
// Insert arrays to find characters that appear in both
char[] inter = s1Chars.Intersect(s2Chars).ToArray();
for (int i = 0; i < inter.Length; i++){
// For each character, put all occurences in their respective array
// Get count
char[] s1Ch = s1.Where(x => x.Equals(inter[i])).ToArray();
char[] s2Ch = s2.Where(x => x.Equals(inter[i])).ToArray();
int s1Count = s1Ch.Length;
int s2Count = s2Ch.Length;
if (s1Count > s2Count)
{
string chars = new String(s1Ch);
sb.Append("1:" + chars + "/");
}
else if (s2Count > s1Count)
{
string chars = new String(s2Ch);
sb.Append("2:" + chars + "/");
}
else if (s1Count == s2Count)
{
string chars = new String(s1Ch);
sb.Append("=:" + chars + "/");
}
}
string final = String.Empty;
string[] strings = sb.ToString().Split('/');
strings = strings.OrderByDescending(x => x.Length).ThenBy(c => c).ToArray(); // "Lexicographical ordering"
final = String.Join("/", strings);
strings = final.Split('/').Where(x => x.Length > 3).Select(x => x).ToArray(); // Remove trailing single characters
final = String.Join("/", strings);
return final;
}
}
}
发生这种情况是因为 '='
在 '1'
和 '2'
之前排序 ;您希望它在 个数字之后 排序。
你可以通过在中间添加特殊条件来强制执行此顺序:
var specialOrder = "12=";
var ordered = data
.OrderByDescending(s => s.Length)
.ThenBy(s => specialOrder.IndexOf(s[0])) // <<== Add this
.ThenBy(s => s);
这将确保初始字符按照specialOrder
字符串中字符的顺序排序,即'1'
,然后是'2'
,然后是'='
。
注意:代码假设序列没有空字符串。你的代码确保每个字符串至少有三个字符,所以这不是问题。