比较两个列表并找到这两个列表之间的增量的最有效的模式/算法是什么?

发布于 2024-09-18 19:55:08 字数 2734 浏览 1 评论 0原文

我们有两个列表,比如说学生和他们的分数。我想比较这两个列表并找到新列表和旧列表之间的增量,然后找到侵入性最小的方式将任何更改插入或更新到新列表中。解决这个问题的最佳算法是什么?希望专注于对新列表和性能进行最少的更改。

示例代码:

List<ListItem> existingList = new List<ListItem>();
List<ListItem> newList = new List<ListItem>();

public TopLists()
{
  InitTwoLists();
}

private void InitTwoLists()
{
  existingList.Add(new ListItem { Name = "Shane", Score = 100 });
  existingList.Add(new ListItem { Name = "Mark", Score = 95 });
  existingList.Add(new ListItem { Name = "Shane", Score = 94 });
  existingList.Add(new ListItem { Name = "Steve", Score = 90 });
  existingList.Add(new ListItem { Name = "Brian", Score = 85 });
  existingList.Add(new ListItem { Name = "Craig", Score = 85 });
  existingList.Add(new ListItem { Name = "John", Score = 82 });
  existingList.Add(new ListItem { Name = "Steve", Score = 81 });
  existingList.Add(new ListItem { Name = "Philip", Score = 79 });
  existingList.Add(new ListItem { Name = "Peter", Score = 70 });

  newList.Add(new ListItem { Name = "Shane", Score = 100 });
  newList.Add(new ListItem { Name = "Steve", Score = 96 });  // This is change
  newList.Add(new ListItem { Name = "Mark", Score = 95 });
  newList.Add(new ListItem { Name = "Shane", Score = 94 });
  newList.Add(new ListItem { Name = "Brian", Score = 85 });
  newList.Add(new ListItem { Name = "Craig", Score = 85 });
  newList.Add(new ListItem { Name = "John", Score = 82 });
  newList.Add(new ListItem { Name = "Steve", Score = 81 });
  newList.Add(new ListItem { Name = "Philip", Score = 79 });
  newList.Add(new ListItem { Name = "Peter", Score = 70 });
}
}

public void CompareLists()
{
  // How would I find the deltas and update the new list with any changes from old?
}
}

public class ListItem
{
  public string Name { get; set; }
  public int Score { get; set; }
}

** 编辑:所需输出 ***

所需输出是实际更改带有增量的 newList。 例如,在这种情况下:

newList.Add(new ListItem { Name = "Shane", Score = 100 });
  newList.Add(new ListItem { Name = "Steve", Score = 96 });  // This is change
  newList.Add(new ListItem { Name = "Mark", Score = 95 });
  newList.Add(new ListItem { Name = "Shane", Score = 94 });
  newList.Add(new ListItem { Name = "Brian", Score = 85 });
  newList.Add(new ListItem { Name = "Craig", Score = 85 });
  newList.Add(new ListItem { Name = "John", Score = 82 });
  newList.Add(new ListItem { Name = "Steve", Score = 81 });
  newList.Add(new ListItem { Name = "Roger", Score = 80 });  // Roger is a new entry
  newList.Add(new ListItem { Name = "Phillip", Score = 79 });  // Philip moved down one

// Peter 以其 70 分的成绩从该列表中删除,因为我只想要前 10 名。

因此更改将是:

更新“Steve”的记录 2,分数已更改 在位置 9 插入新记录“Roger” 打破了“Peter”跌出前十名的记录。

We have two lists, let's say students and their scores. I want to compare these two lists and find the delta between the new list and the old list, then find the least intrusive way to Insert or Update into the new list any changes. What is the best algorithm to approach this? Want to focus on minimal amount of changes to new list and performance.

Example code:

List<ListItem> existingList = new List<ListItem>();
List<ListItem> newList = new List<ListItem>();

public TopLists()
{
  InitTwoLists();
}

private void InitTwoLists()
{
  existingList.Add(new ListItem { Name = "Shane", Score = 100 });
  existingList.Add(new ListItem { Name = "Mark", Score = 95 });
  existingList.Add(new ListItem { Name = "Shane", Score = 94 });
  existingList.Add(new ListItem { Name = "Steve", Score = 90 });
  existingList.Add(new ListItem { Name = "Brian", Score = 85 });
  existingList.Add(new ListItem { Name = "Craig", Score = 85 });
  existingList.Add(new ListItem { Name = "John", Score = 82 });
  existingList.Add(new ListItem { Name = "Steve", Score = 81 });
  existingList.Add(new ListItem { Name = "Philip", Score = 79 });
  existingList.Add(new ListItem { Name = "Peter", Score = 70 });

  newList.Add(new ListItem { Name = "Shane", Score = 100 });
  newList.Add(new ListItem { Name = "Steve", Score = 96 });  // This is change
  newList.Add(new ListItem { Name = "Mark", Score = 95 });
  newList.Add(new ListItem { Name = "Shane", Score = 94 });
  newList.Add(new ListItem { Name = "Brian", Score = 85 });
  newList.Add(new ListItem { Name = "Craig", Score = 85 });
  newList.Add(new ListItem { Name = "John", Score = 82 });
  newList.Add(new ListItem { Name = "Steve", Score = 81 });
  newList.Add(new ListItem { Name = "Philip", Score = 79 });
  newList.Add(new ListItem { Name = "Peter", Score = 70 });
}
}

public void CompareLists()
{
  // How would I find the deltas and update the new list with any changes from old?
}
}

public class ListItem
{
  public string Name { get; set; }
  public int Score { get; set; }
}

** EDIT: Desired Output ***

The desired output is to actually change the newList with the deltas.
For example in this scenario:

newList.Add(new ListItem { Name = "Shane", Score = 100 });
  newList.Add(new ListItem { Name = "Steve", Score = 96 });  // This is change
  newList.Add(new ListItem { Name = "Mark", Score = 95 });
  newList.Add(new ListItem { Name = "Shane", Score = 94 });
  newList.Add(new ListItem { Name = "Brian", Score = 85 });
  newList.Add(new ListItem { Name = "Craig", Score = 85 });
  newList.Add(new ListItem { Name = "John", Score = 82 });
  newList.Add(new ListItem { Name = "Steve", Score = 81 });
  newList.Add(new ListItem { Name = "Roger", Score = 80 });  // Roger is a new entry
  newList.Add(new ListItem { Name = "Phillip", Score = 79 });  // Philip moved down one

// Peter drops off this list with his score of 70, since I only want the top 10.

So the changes would be:

Update record 2 for "Steve", the score has changed
Insert new record "Roger" at position 9
Drop record for "Peter" off of the top 10.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

薄凉少年不暖心 2024-09-25 19:55:08

如果您正在寻找通用的、与语言无关的解决方案,那么您正在寻找某种 有序列表的数据同步。基本算法是:

i1 = 0
i2 = 0
while (i1 < list1.size && i2 < list2.size)
{
  if (list1[i1] < list2[i2])
  {
    //list1[i1] is not in list2
    i1++
  }
  else if (list1[i1] > list2[i2])
  {
    //list2[i2] is not in list1
    i2++
  }
  else
  {
    //item is in both lists
    i1++
    i2++
  }
}
if (i1 < list1.size)
   //all remaining list1 items are not in list2
if (i2 < list2.size)
   //all remaining list2 items are not in list1

If you're looking for a general, language-agnostic solution, then you're looking for some kind of data synchronization of ordered lists. The basic algorithm would be:

i1 = 0
i2 = 0
while (i1 < list1.size && i2 < list2.size)
{
  if (list1[i1] < list2[i2])
  {
    //list1[i1] is not in list2
    i1++
  }
  else if (list1[i1] > list2[i2])
  {
    //list2[i2] is not in list1
    i2++
  }
  else
  {
    //item is in both lists
    i1++
    i2++
  }
}
if (i1 < list1.size)
   //all remaining list1 items are not in list2
if (i2 < list2.size)
   //all remaining list2 items are not in list1
纵性 2024-09-25 19:55:08

您可以使用 Linq:

List<ListItem> list1 = GetYourList1();
List<ListItem> list2 = GetYourList2();
var diff = list1.Except(list2);

您的具体示例:

var diff = newList.Except(existingList);

不确定它是否是最有效的,但它很简洁:)

Can you use Linq:

List<ListItem> list1 = GetYourList1();
List<ListItem> list2 = GetYourList2();
var diff = list1.Except(list2);

Your example specific:

var diff = newList.Except(existingList);

Not sure if it is the most efficient but it's concise :)

转瞬即逝 2024-09-25 19:55:08

如果您的列表中没有两次出现相同的名称,这应该能够解决问题。在您的示例中,您有 2 个 Steve,但您需要一种方法来区分他们。

public static List<ListItem> CompareLists(List<ListItem> existingList, List<ListItem> newList)
{
    List<ListItem> mergedList = new List<ListItem>();
    mergedList.AddRange(newList);
    mergedList.AddRange(existingList.Except(newList, new ListItemComparer()));
    return mergedList.OrderByDescending(x => x.Score).Take(10).ToList();
}

public class ListItemComparer : IEqualityComparer<ListItem>
{
    public bool Equals(ListItem x, ListItem y)
    {
        return x.Name == y.Name;
    }

    public int GetHashCode(ListItem obj)
    {
        return obj.Name.GetHashCode();
    }
}

你可以这样称呼它:

newList = CompareLists(existingList, newList);

This should be able to do the trick if you don't have the same name twice in your list. In your example, you have 2x Steve, but you need a way to distinct between them.

public static List<ListItem> CompareLists(List<ListItem> existingList, List<ListItem> newList)
{
    List<ListItem> mergedList = new List<ListItem>();
    mergedList.AddRange(newList);
    mergedList.AddRange(existingList.Except(newList, new ListItemComparer()));
    return mergedList.OrderByDescending(x => x.Score).Take(10).ToList();
}

public class ListItemComparer : IEqualityComparer<ListItem>
{
    public bool Equals(ListItem x, ListItem y)
    {
        return x.Name == y.Name;
    }

    public int GetHashCode(ListItem obj)
    {
        return obj.Name.GetHashCode();
    }
}

You can call it like this:

newList = CompareLists(existingList, newList);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文