2012-04-10 148 views
2

删除丢失数字有两个列表:比较两个列表,并与C#

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 }); 

你如何比较两个列表,寻找失踪的数字在列表1和列表1中移除这些数字?更确切地说,我需要找到一种方法来指定开始和结束位置进行比较。

我想象proccess应该很类似:

第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) 

现在我们已经有了数(和数字本身)的位置在列表2比较(3,5,6)

第2步:要获得比较List1中号的位置 - 我们可以做到以下几点:

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

该范围如下:(3,4,5,6)

步骤3.比较。棘手的部分从这里开始,我需要帮助

现在基本上我们需要比较(3,5,6)的list2和(3,4,5,6)的list1。缺少的数字是“4”。

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

int remove_it = 4; // or int [] 

第4步:奇数删除。

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

很好,但如果我们有2个缺失的数字会发生什么?即

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

结果正如你已经猜到了结果是新的列表1,没有它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 

你能家伙帮我出第3步或点我到正确的方向?

另外,你可以说如果开始数字(start_num)是最后一个数字会发生什么,但我需要得到接下来的两个数字?在例如由上面的数字为3,5,6,但它们应该没有不同于5,6,06,0,10,1,2

+2

我不明白“在列表1中查找缺少的数字,并从列表1中删除这些项目” – tsiorn 2012-04-10 13:29:22

+0

列表2不包含数字4但列表1。这个想法是从list1中删除这个数字。但是,这不是问题。问题是在给定的位置开始列表比较。不是从一开始,但让我们说 - 从最后。我们仅比较列表中的一小部分,而不是全部。此外,假设如果我们在列表的末尾开始起始位置是合乎逻辑的 - 由于“超出范围”错误,我们将无法比较两个下一个数字。这就是为什么继续比较从名单开始至关重要的原因,即5,6,0 - 0是从开始开始 – Alex 2012-04-10 14:51:42

+0

您需要更清楚地了解此目的和使用情况。 – 2012-04-11 09:58:03

回答

0

好的,好像我没有足够好地解释这个问题,对此抱歉。任何有兴趣的可以理解了我的意思看这段代码:

 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 

是否有优化的代码,请告诉我任何方式。干杯。

1
var result = list1.Intersect(list2) 

如果您确实需要将结果作为列表,您可以在末尾添加.ToList

+0

这给了差异('{0,4}') – 2012-04-10 13:30:39

+0

@HenkHolterman正确,这就是我得到的不仔细阅读。 – Servy 2012-04-10 13:38:42

3

只是回答的第一部分:

var list3 = list1.Intersect(list2); 

这将设置list3{ 0, 1, 2, 3, 4, 5, 6 } - { 0, 4 } = { 1, 2, 3, 5, 6 }

并以步骤1反应:

INT START_NUM = 3; //我们知道比较从第3个开始
int start = list2.IndexOf(start_num); //我们得到索引号(3)
int end = start + 2; //获取结束位置

从哪里得到所有这些幻数(3,+ 2)?

我觉得你是这么想的。

+0

3不是一个常数。它可以是列表中的任何数字。另一方面,数字2是不变的。我需要比较右边的两个数字。 – Alex 2012-04-10 14:37:46

+0

如果“右边的两个数字”不存在,会发生什么情况?超出范围的异常被抛出。除非我们从列表的开头得到这个数字。看,** 3,5,6 ** - 不会抛出异常。 ** 5,6, - ** - 列表中没有数字7,所以我们希望从列表开始处继续,因此结果应该如下:5,6,0。 ** 6, - , - **没有7和8,但有0和1,所以** 6,0,1 ** – Alex 2012-04-10 15:11:27

0

也许你应该与OrderedList而不是List工作...

0

事情是这样的:

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

您可以结合使用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(); 
} 

虽然如果我是真的说实话,我不知道问什么 - 我在一定的唯一的事情是相交部分:

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. 
0

要获得存在于list1的电话号码,但没有list2,您使用该Except扩展方法:

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

要遍历这个结果从list1删除它们,你必须认识的结果,否则会从列表中,而你正在改变它读,你会得到一个异常:

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

现在,你可以将其删除:

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

我不知道我理解你的问题,我希望解决我给你是对你有好处。

您有2所列出:

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

从列表1所有list2中丢失号码,我建议这个解决方案中删除: 建立与丢失号码的新列表:

列表DIFF =新名单();

然后把你需要删除的所有数字放在这个列表中。现在,删除过程应该很简单,只需将您在diff中添加的所有元素和从list2中删除。

0

难道我理解正确的是算法是: 1)采取列表2第一个号码并找到列表1这样的数量, 2),然后从列表1中取出的一切,直到你找到第二个数字形式列表2(5) 3)重复步骤2)为list2中的下一个数字。

+0

需要这些数字来定义循环内**范围的数字**开始:结束)。首先,我从第二个列表中获取一系列数字,并将这些数字与第一个列表中的相同范围进行比较。如果range2有一些缺失的号码 - 我从另一个列表中删除这个号码。 – Alex 2012-04-10 14:42:41

1
 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);