简体   繁体   English

使用 C# 比较两个列表并删除缺失的数字

[英]comparing two lists and removing missing numbers with C#

there are two lists:有两个列表:

List<int> list2 = new List<int>(new[] { 1, 2, 3, 5, 6 }); // missing: 0 and 4
List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 });

how do you compare two lists, find missing numbers in List1 and remove these numbers from List1?你如何比较两个列表,找到 List1 中缺失的数字并将这些数字从 List1 中删除? To be more precise, I need to find a way to specify starting and ending position for comparison.更准确地说,我需要找到一种方法来指定开始和结束 position 以进行比较。

I imagine that the proccess should be very similar to this:我想这个过程应该与此非常相似:

Step 1.步骤1。

int start_num = 3; // we know that comparisons starts at number 3
int start = list2.IndexOf(start_num); // we get index of Number (3)
int end = start + 2; // get ending position
int end_num = list2[end]; // get ending number (6)

now we've got positions of numbers (and numbers themselves) for comparison in List2 (3,5,6)现在我们在 List2 (3,5,6) 中得到了用于比较的数字位置(和数字本身)

Step 2. To get positions of numbers in List1 for comparison - we can do the following:第 2 步。要获取数字在 List1 中的位置以进行比较 - 我们可以执行以下操作:

int startlist1 = list1.IndexOf(start_num); // starting position
int endlist1 = list1.IndexOf(end_num); // ending position

the range is following: (3,4,5,6)范围如下:(3,4,5,6)

Step 3. Comparison.步骤 3. 比较。 Tricky part starts here and I need a help with it棘手的部分从这里开始,我需要帮助

Basically now we need to compare list2 at (3,5,6) with list1 at (3,4,5,6).基本上现在我们需要比较 list2 在 (3,5,6) 和 list1 在 (3,4,5,6)。 The missing number is "4".缺少的数字是“4”。

// I have troubles with this step but the result will be:

int remove_it = 4; // or int []

Step 4. Odd number removal.第四步,去除奇数。

int remove_it = 4;
list1 = list1.Where(a => a != remove_it).ToList();

works great, but what will happen if we have 2 missing numbers?效果很好,但是如果我们缺少 2 个数字会怎样? ie IE

int remove_it = 4 // becomes int[] remove_it = {4, 0}

Result As you have guessed the result is new List1, without number 4 in it.结果正如您所猜到的,结果是新的 List1,其中没有数字 4。

richTextBox1.Text = "" + string.Join(",", list1.ToArray()); // output: 0,1,2,3,5,6

textBox1.Text = "" + start + " " + start_num; // output: 2 3
textBox3.Text = "" + end + " " + end_num; // output: 4 6

textBox2.Text = "" + startlist1; // output: 3
textBox4.Text = "" + endlist1; // output: 6

Can you guy help me out with Step 3 or point me out to the right direction?你们能帮我解决第 3 步或指出正确的方向吗?

Also, can you say what will happen if starting number(start_num) is the last number, but I need to get next two numbers?另外,你能说如果起始号码(start_num)是最后一个号码会发生什么,但我需要得到接下来的两个号码吗? In example from above numbers were 3,5,6, but they should be no different than 5,6,0 or 6,0,1 or 0,1,2 .在上面的示例中,数字是3,5,6,但它们应该与5,6,06,0,10,1,2没有区别。

Just answering the first part:只回答第一部分:

 var list3 = list1.Intersect(list2);

This will set list3 to { 0, 1, 2, 3, 4, 5, 6 } - { 0, 4 } = { 1, 2, 3, 5, 6 }这会将list3设置为{ 0, 1, 2, 3, 4, 5, 6 } - { 0, 4 } = { 1, 2, 3, 5, 6 }

And a reaction to step 1 :以及对第 1 步的反应:

int start_num = 3; int start_num = 3; // we know that comparisons starts at number 3 // 我们知道比较从数字 3 开始
int start = list2.IndexOf(start_num); int start = list2.IndexOf(start_num); // we get index of Number (3) // 我们得到 Number (3) 的索引
int end = start + 2; int 结束 = 开始 + 2; // get ending position // 得到结尾 position

From where do you get all those magic numbers (3, + 2 )?你从哪里得到所有这些神奇的数字 (3, + 2 )?

I think you are over-thinking this, a lot.我认为你想得太多了。

var result = list1.Intersect(list2)

You can add a .ToList on the end if you really need the result to be a list.如果你真的需要结果是一个列表,你可以在最后添加一个.ToList

        List<int> list2 = new List<int>(new[] { 1, 2, 3, 5, 6 }); // missing: 0 and 4 
        List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 });

        // find items in list 2 notin 1
        var exceptions = list1.Except(list2);

        // or are you really wanting to do a union? (unique numbers in both arrays)
        var uniquenumberlist = list1.Union(list2);

        // or are you wanting to find common numbers in both arrays
        var commonnumberslist = list1.Intersect(list2);

maybe you should work with OrderedList instead of List...也许您应该使用 OrderedList 而不是 List...

Something like this:像这样:

list1.RemoveAll(l=> !list2.Contains(l));

You can use Intersect in conjunction with Skip and Take to get the intersection logic combined with a range (here we ignore the fact 0 is missing as we skip it):您可以将IntersectSkipTake结合使用,以获得与范围相结合的交集逻辑(此处我们忽略缺少 0 的事实,因为我们跳过它):

static void Main(string[] args)
{
    var list1 = new List<int> { 1, 2, 3, 4, 5 };
    var list2 = new List<int> { 0, 1, 2, 3, 5, 6 };

    foreach (var i in list2.Skip(3).Take(3).Intersect(list1))
        Console.WriteLine(i); // Outputs 3 then 5.

    Console.Read();
}

Though if I'm being really honest, I'm not sure what is being asked - the only thing I'm certain on is the intersect part:虽然如果我真的很诚实,我不确定被问到什么 - 我唯一确定的是相交部分:

var list1 = new List<int> { 1, 2, 3, 4, 5 };
var list2 = new List<int> { 0, 1, 2, 3, 5, 6 };

foreach (var i in list2.Intersect(list1))
    Console.WriteLine(i); // Outputs 1, 2, 3, 5.

To get the numbers that exist in list1 but not in list2 , you use the Except extension method:要获取list1中存在但list2中不存在的数字,您可以使用Except扩展方法:

IEnumerable<int> missing = list1.Except(list2);

To loop through this result to remove them from list1 , you have to realise the result, otherwise it will read from the list while you are changing it, and you get an exception:要遍历此结果以将它们从list1中删除,您必须实现结果,否则它会在您更改列表时从列表中读取,并且您会得到一个异常:

List<int> missing = list1.Except(list2).ToList();

Now you can just remove them:现在你可以删除它们:

foreach (int number in missing) {
  list1.Remove(number);
}

I'm not sure I understand your issue, and I hope the solution I give you to be good for you.我不确定我是否理解您的问题,希望我给您的解决方案对您有好处。

You have 2 lists:你有 2 个列表:

List list2 = new List(new[] { 1, 2, 3, 5, 6 });列表 list2 = new List(new[] { 1, 2, 3, 5, 6 }); // missing: 0 and 4 List list1 = new List(new[] { 0, 1, 2, 3, 4, 5, 6 }); // 缺少:0 和 4 List list1 = new List(new[] { 0, 1, 2, 3, 4, 5, 6 });

To remove from list1 all the missing numbers in list2 I suggest this solution: Build a new list with missing numbers:要从 list1 中删除 list2 中所有缺失的数字,我建议采用以下解决方案:Build a new list with missing numbers:

List diff = new List();列表差异=新列表();

then put all the numbers you need to remove in this list.然后将您需要删除的所有号码放入此列表中。 Now the remove process should be simple, just take all the elements you added in diff and remove from list2.现在删除过程应该很简单了,只需取出您在 diff 中添加的所有元素并从 list2 中删除即可。

Did I understand correctly that algorithm is: 1) take first number in List 2 and find such number in List1, 2) then remove everything from list 1 until you find second number form list2 (5) 3) repeat step 2) for next number in list2.?我是否正确理解算法是:1) 取列表 2 中的第一个数字并在列表 1 中找到该数字,2) 然后从列表 1 中删除所有内容,直到找到列表 2 (5) 中的第二个数字 3) 重复步骤 2) 获取下一个数字在列表 2 中。

ok, seems like I hadn't explained the problem well enough, sorry about it.好的,看来我没有很好地解释问题,对此感到抱歉。 Anyone interested can understand what I meant by looking at this code:有兴趣的可以看看这段代码就明白我的意思了:

        List<int> list2 = new List<int>() { 1, 2, 3, 5, 6 }; // missing: 0 and 4
        List<int> list1 = new List<int>() { 0, 1, 2, 3, 4, 5, 6 };

        int number = 3; // starting position

        int indexer = list2.BinarySearch(number);
        if (indexer < 0)
        {
            list2.Insert(~index, number); // don't look at this part
        }

        // get indexes of "starting position"
        int index1 = list1.Select((item, i) => new { Item = item, Index = i }).First(x => x.Item == number).Index;
        int index2 = list2.Select((item, i) => new { Item = item, Index = i }).First(x => x.Item == number).Index;

        // reorder lists starting at "starting position"
        List<int> reorderedList1 = list1.Skip(index1).Concat(list1.Take(index1)).ToList(); //main big
        List<int> reorderedList2 = list2.Skip(index2).Concat(list2.Take(index2)).ToList(); // main small


        int end = 2; // get ending position: 2 numbers to the right
        int end_num = reorderedList2[end]; // get ending number

        int endlist1 = reorderedList1.IndexOf(end_num); // ending position

        //get lists for comparison
        reorderedList2 = reorderedList2.Take(end + 1).ToList();
        reorderedList1 = reorderedList1.Take(endlist1 + 1).ToList();

        //compare lists
        var list3 = reorderedList1.Except(reorderedList2).ToList();
        if (list3.Count != 0)
        {
            foreach (int item in list3)
            {
                list1 = list1.Where(x => x != item).ToList(); // remove from list
            }
        }
        // list1 is the result that I wanted to see

if there are any ways to optimize this code please inform me.如果有任何方法可以优化此代码,请通知我。 cheers.干杯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM