我有2个不同类型的列表。我认为现在并不重要的是什么类型。 两种类型都有关于出现的信息,这些信息以刻度形式出现(但也可以是日期时间)。
我想要做的是,按时间同步这两个列表,例如我可以按时间顺序遍历所有元素。
Example: // in this example List has elements called A_NUM or B_NUM depending on a type of list and number after '_' will represent order at which this elements/events occured
ListA = {A_2, A_3, A_5}
ListB = {B_1, B_4, B_6}
同步后的结果将是这样的:
ResultList = {B_1, A_2, A_3, B_4, A_5, B_6}
是否有可能制作这样的混合列表?或者我必须创建一些辅助列表或字典,它会告诉我这2个列表的同步顺序?
修改
一个列表是眼睛注视列表。固定有一个位置,持续时间,......以及出现属性。
第二个列表是文本的一些更改列表,例如在第12行第3列中有一个字符' x'在某个时间添加t
。
我想同时迭代这两个列表。我的意思是t1
在x,y
位置t2
发生了固定。在u,v
时,位置@Injectable()
export class MyService {
public invokeEvent:Subject<any> = new Subject();
constructor() {}
}
发生了文字更改,因此我希望及时按顺序迭代这些事件。
注意:是两个列表都按时间排序。它是一系列固定和文本变化的序列。
答案 0 :(得分:3)
您的问题强烈建议将合并排序作为基本实现细节。你有两个输入,都是排序的,只是希望它们按顺序合并在一起。
您的问题隐含的主要困难是您尝试合并两个完全不相关的类型的序列。通常,您将合并相同类型的序列,因此可以轻松地将它们一起操作。除此之外,他们至少共享基类或接口类型,以便您可以将它们视为单一的通用类型。但从您的问题来看,似乎并非如此。
鉴于此,我认为最直接的方法仍然是使用合并排序,但提供一种机制来进行排序以访问相关属性(ticks,DateTime
,等等)。排序将以正确的顺序返回合并的序列,作为object
类型(即两个输入共有的唯一基类型),然后调用者必须为了任何目的而回送到各个类型。
这是我的意思的一个例子:
private static IEnumerable<TBase> Merge<TBase, T1, T2, TValue>(
IEnumerable<T1> sequence1, IEnumerable<T2> sequence2,
Func<T1, TValue> valueSelector1, Func<T2, TValue> valueSelector2)
where T1 : TBase
where T2 : TBase
where TValue : IComparable<TValue>
{
IEnumerator<T1> enumerator1 = sequence1.GetEnumerator();
IEnumerator<T2> enumerator2 = sequence2.GetEnumerator();
bool notDone1 = enumerator1.MoveNext(),
notDone2 = enumerator2.MoveNext();
while (notDone1 && notDone2)
{
TValue value1 = valueSelector1(enumerator1.Current),
value2 = valueSelector2(enumerator2.Current);
if (value1.CompareTo(value2) <= 0)
{
yield return enumerator1.Current;
notDone1 = enumerator1.MoveNext();
}
else
{
yield return enumerator2.Current;
notDone2 = enumerator2.MoveNext();
}
}
while (notDone1)
{
yield return enumerator1.Current;
notDone1 = enumerator1.MoveNext();
}
while (notDone2)
{
yield return enumerator2.Current;
notDone2 = enumerator2.MoveNext();
}
}
像这样使用:
class A
{
public int Value { get; }
public A(int value)
{
Value = value;
}
}
class B
{
public int Value { get; }
public B(int value)
{
Value = value;
}
}
static void Main(string[] args)
{
const int minCount = 5, maxCount = 15, maxValue = 50;
Random random = new Random();
int listACount = random.Next(minCount, maxCount),
listBCount = random.Next(minCount, maxCount);
A[] listA = RandomOrderedSequence(random, maxValue, listACount).Select(i => new A(i)).ToArray();
B[] listB = RandomOrderedSequence(random, maxValue, listBCount).Select(i => new B(i)).ToArray();
Console.WriteLine("listA: ");
Console.WriteLine(string.Join(", ", listA.Select(a => a.Value)));
Console.WriteLine("listB: ");
Console.WriteLine(string.Join(", ", listB.Select(b => b.Value)));
foreach (object o in Merge<object, A, B, int>(listA, listB, a => a.Value, b => b.Value))
{
A a = o as A;
if (a != null)
{
// Do something with object of type A
Console.WriteLine($"a.Value: {a.Value}");
}
else
{
// Must be a B. Do something with object of type B
B b = (B)o;
Console.WriteLine($"b.Value: {b.Value}");
}
}
}
static IEnumerable<int> RandomOrderedSequence(Random random, int max, int count)
{
return RandomSequence(random, max, count).OrderBy(i => i);
}
static IEnumerable<int> RandomSequence(Random random, int max, int count)
{
while (count-- > 0)
{
yield return random.Next(max);
}
}
在您的情况下,您当然会将类型A
和B
替换为您实际使用的类型,提供适当的选择器,然后根据合并返回的每个实例执行您喜欢的任何操作,按顺序。
请注意,即使这些类型确实共享一些可以比较和合并的公共基础,我仍然建议合并排序而不是简单地连接和合并结果。合并排序是一种很多更有效的方法,可以将已排序的数据合并为单个有序数据序列。
答案 1 :(得分:0)
您需要列表来实现通用接口,以便对它们进行比较。例如:
public interface ISynchronizable
{
long GetTicks();
}
所以你需要让两个对象实现它,如下所示:
public class Fixation : ISynchronizable
{
public long GetTicks()
{
// get the ticks
}
// some other code
}
public class TextChange: ISynchronizable
{
public long GetTicks()
{
// get the ticks
}
// some other code
}
然后结果列表将如下创建:
public List<ISynchronizable> list = new List<ISynchronizable>();
list.AddRange(fixationList);
list.AddRange(textChangeList);
resultList = list.OrderBy(e => e.GetTicks()).ToList();