我需要一种各种记录器,并且必须不时地转储内容。 我想只获取每个项目的最后一个实例并保留该顺序。
有没有比这更好的方法呢? List.contains是昂贵的,但我不满意额外的hashset的内存开销。
public List<Int3> UnsafeDumpMostRecentUsageLast() {
HashSet<Int3> _containsHelper = new HashSet<Int3>();
List<Int3> uniqueOccurencesOrdered = new List<Int3>(uniqueConsumedCount);
for (int i = usageLog.Length-1;i >= 0; i--) {
if (_containsHelper.Add(usageLog[i]))
uniqueOccurencesOrdered.Add(usageLog[i]);
}
uniqueOccurencesOrdered.Reverse();
return uniqueOccurencesOrdered;
}
要清除它..说我有这样的清单:
aabbbaabbbccabccccdeddaccc
我想返回一个返回大写字母的列表:
aabbbaabbbccaBccccdEdDAccC
所以列表将是:BEDAC
加: AaBbbaabbbCcabccccDEddaccc
ABCDE
答案 0 :(得分:1)
我不确定Int3
类型是什么,但如果我们假设我们正在讨论int(在其他情况下工作方式类似)而usageLog
是IEnumerable
则可以执行以下内容:
public List<Int3> UnsafeDumpMostRecentUsageLast() {
return usageLog.Distinct().ToList();
}
<强>加成强>
如果您的列表已经排序,并且您只想保留每个实例的最后一次出现(如您的评论所示):
usageLog.Reverse().Distinct().Reverse().ToList();
答案 1 :(得分:1)
您可以这样做:
var str = "aabbbaabbbccabccccdeddaccc";
var result = new string(str
.Reverse()
.Distinct()
.Reverse()
.ToArray()
);
答案 2 :(得分:0)
基于哈希的查找为您提供最佳的时间复杂度(因此性能)。如果您对HashSet
类空间开销(以及扩展内部存储和重新散列的额外成本)不满意,那么创建特定于所需操作的哈希结构并不困难。
例如,以下算法使用大小为int
的2 N
个数组来实现相同的目标,而且开销更少。名为head
的第一个数组用于散列表存储桶链接列表开始索引,而next
包含存储桶中下一个条目的索引,并且还用于标识最后的唯一条目。不需要存储值,因为我们已经拥有它们,整个映射是索引。
static List<T> UnsafeDumpMostRecentUsageLast<T>(IReadOnlyList<T> source, IEqualityComparer<T> comparer = null)
{
var head = new int[source.Count];
var next = new int[source.Count];
int count = 0;
if (comparer == null) comparer = EqualityComparer<T>.Default;
for (int i = 0; i < source.Count; i++)
{
var item = source[i];
// Check for duplicate
int bucket = (comparer.GetHashCode(item) & int.MaxValue) % head.Length;
int prev = -1, last = head[bucket] - 1;
while (last >= 0 && !comparer.Equals(source[last], item))
last = next[prev = last];
if (last >= 0)
{
// Found, replace it in the hash chain (we need only the last)
next[i] = next[last];
if (prev >= 0)
next[prev] = i;
else
head[bucket] = i + 1;
// Use int.MinValue (value < -1) to mark the duplicate entry as not being last
next[last] = int.MinValue;
}
else
{
next[i] = head[bucket];
head[bucket] = i + 1;
count++;
}
}
var result = new List<T>(count);
for (int i = 0; i < next.Length; i++)
{
if (next[i] < -1) continue;
result.Add(source[i]);
if (result.Count == count) break;
}
return result;
}
以下是您的用法:
public List<Int3> UnsafeDumpMostRecentUsageLast()
{
return UnsafeDumpMostRecentUsageLast(usageLog);
}
和测试:
var source = "aabbbaabbbccabccccdeddaccc".ToCharArray();
var result = UnsafeDumpMostRecentUsageLast(source);
Console.WriteLine(string.Concat(result));
// output: bedac