按给定的排序顺序排列集合
order collection by given sort order
我有一个字符串列表,我想按特定顺序引入。假设该列表包含随机数量的字符串 "A"、"B" 和 "C"。我还有另一个包含排序顺序的字符串列表。
例如:
对于输入:
"A"
"A"
"C"
"B"
"B"
"C"
排序顺序列表:
- "A"
- "B"
- "C"
我想订购这个输出如下所示的列表:
- "A"
- "B"
- "C"
- "A"
- "B"
- "C"
另一个例子:
对于输入:
- "A"
- "A"
- "C"
- "B"
- "C"
排序顺序列表:
- "A"
- "C"
- "B"
输出应如下所示:
- "A"
- "C"
- "B"
- "A"
- "C"
注意:我选择 A、B 和 C 只是为了简单起见,所以在我的实际应用中我将无法使用任何字母顺序。
有什么方法可以达到想要的效果吗?几天来我一直在思考这个问题,但没有想出解决方案。我试图实现 IComparer 但我一直在为比较方法的条件而苦苦挣扎。
我认为这符合您的需求:
var list = new List<string> { "A", "B", "E", "A", "E", "A", "B", "E", "C", "B", "A", "D", "B", "E" };
var sortOrder = new List<string> { "F", "E", "C", "A", "B", "D" };
var resultSets = new List<List<string>> ();
for (int i = 0; i < sortOrder.Count(); i++)
{
var currentLetter = sortOrder[i];
for (int j = 0; j < list.Count(x=> x == currentLetter); j++)
{
if(resultSets.Count() < j + 1)
{
resultSets.Add(new List<string>());
}
resultSets[j].Add(currentLetter);
}
}
var result = string.Join(", ", resultSets.SelectMany(x => x));
Console.WriteLine($"Results: { result}");
尽管接受的答案有效,但如果输入枚举 and/or 模式足够大,则性能简直太可怕了。如果您为作业选择更合适的集合,您可以获得显着的性能提升::
public static IEnumerable<T> GetChunks<T>(this IEnumerable<T> source, IEnumerable<T> pattern)
where T: IEquatable<T>
{
var dictionary = pattern.ToDictionary(p => p, p => new Stack<T>());
foreach (var item in source)
{
dictionary[item].Push(item);
}
var rest = source.Except(pattern);
while (dictionary.Values.Any(q => q.Any()))
{
foreach (var p in pattern)
{
if (dictionary[p].Count >0)
{
yield return dictionary[p].Pop();
}
}
}
foreach (var r in rest)
{
yield return r;
}
}
这里的诀窍是预先构建一个便宜的字典,以利用它提供的更快的查找速度。
我还冒昧地决定将所有不匹配的元素添加到 "ordered" 结果的末尾。这可能不是您想要的,但此区域中的问题未指定。
我有一个字符串列表,我想按特定顺序引入。假设该列表包含随机数量的字符串 "A"、"B" 和 "C"。我还有另一个包含排序顺序的字符串列表。
例如: 对于输入:
"A"
"A"
"C"
"B"
"B"
"C"
排序顺序列表:
- "A"
- "B"
- "C"
我想订购这个输出如下所示的列表:
- "A"
- "B"
- "C"
- "A"
- "B"
- "C"
另一个例子:
对于输入:
- "A"
- "A"
- "C"
- "B"
- "C"
排序顺序列表:
- "A"
- "C"
- "B"
输出应如下所示:
- "A"
- "C"
- "B"
- "A"
- "C"
注意:我选择 A、B 和 C 只是为了简单起见,所以在我的实际应用中我将无法使用任何字母顺序。
有什么方法可以达到想要的效果吗?几天来我一直在思考这个问题,但没有想出解决方案。我试图实现 IComparer 但我一直在为比较方法的条件而苦苦挣扎。
我认为这符合您的需求:
var list = new List<string> { "A", "B", "E", "A", "E", "A", "B", "E", "C", "B", "A", "D", "B", "E" };
var sortOrder = new List<string> { "F", "E", "C", "A", "B", "D" };
var resultSets = new List<List<string>> ();
for (int i = 0; i < sortOrder.Count(); i++)
{
var currentLetter = sortOrder[i];
for (int j = 0; j < list.Count(x=> x == currentLetter); j++)
{
if(resultSets.Count() < j + 1)
{
resultSets.Add(new List<string>());
}
resultSets[j].Add(currentLetter);
}
}
var result = string.Join(", ", resultSets.SelectMany(x => x));
Console.WriteLine($"Results: { result}");
尽管接受的答案有效,但如果输入枚举 and/or 模式足够大,则性能简直太可怕了。如果您为作业选择更合适的集合,您可以获得显着的性能提升::
public static IEnumerable<T> GetChunks<T>(this IEnumerable<T> source, IEnumerable<T> pattern)
where T: IEquatable<T>
{
var dictionary = pattern.ToDictionary(p => p, p => new Stack<T>());
foreach (var item in source)
{
dictionary[item].Push(item);
}
var rest = source.Except(pattern);
while (dictionary.Values.Any(q => q.Any()))
{
foreach (var p in pattern)
{
if (dictionary[p].Count >0)
{
yield return dictionary[p].Pop();
}
}
}
foreach (var r in rest)
{
yield return r;
}
}
这里的诀窍是预先构建一个便宜的字典,以利用它提供的更快的查找速度。
我还冒昧地决定将所有不匹配的元素添加到 "ordered" 结果的末尾。这可能不是您想要的,但此区域中的问题未指定。