2015-04-02 2 views
1

Рассмотрим следующий кодКопировать все совпадающие элементы из одного списка в другой

List<string> one = new List<string>(); 
List<string> two = new List<string>(); 

Список один содержит 3 строки

Test 1 
Test 1 
Test 2 

Как бы соответствовать строке Test 1 и поместить каждую сопрягая строку в List two и удалите соответствующие строки из списка 1, так что осталось только Test 2 строка

Это то, что у меня есть до сих пор

if (one.Any(str => str.Contains("Test 1"))) 
{ 
    //What to do here 
} 

Если я использую AddRange() добавляет весь список один перечислить два

+5

Что вы имеете в виду под этим: * Как бы соответствовать строка теста 1 и положить каждую соответствие строка в списке два *; Что именно вы подразумеваете под * совпадением строки Test 1 * –

+0

Вы ищете 'Intersect' http://www.dotnetperls.com/intersect –

+0

Я предлагаю вам попробовать заглянуть в цикл' foreach' и заставить его зацикливать каждый элемент в списке 1. Если он найдет что-то в списке 1, поместите его в список 2 и удалите его список форм 1. это можно сделать с помощью 'indexOf' и' removeAt'. Я думаю, вы можете понять, как использовать их сами. – maam27

ответ

1

Итак, вы хотите, чтобы удалить все «Test1» из one и добавить их в two. Итак, вы хотите перенести их из одного списка в другой?

string toFind = "Test 1"; 
var foundStrings = one.Where(s => s == toFind); 
if(foundStrings.Any()) 
{ 
    two.AddRange(foundStrings); 
    one.RemoveAll(s => s == toFind); 
} 

Вот версия без LINQ, который является более эффективным, но, возможно, не читаемыми:

// backwards loop because you're going to remove items via index 
for (int i = one.Count - 1; i >= 0; i--) 
{ 
    string s1 = one[i]; 
    if (s1 == toFind) 
    { 
     two.Add(toFind); 
     one.RemoveAt(i); 
    } 
} 
+0

Спасибо за это, это помогло мне много – Izzy

4

задача также может быть решена с помощью Linq следующим образом.

var NewOne = one.Where(iString => iString == "Test1") 
var NewTwo = one.Except(NewOne); 

one = NewOne.ToList(); 
two = NewTwo.ToList(); 
+1

Одним очень важным побочным эффектом «Исключить» является то, что он не только удаляет «Test1», но и любые дубликаты. Это потому, что 'Except' является * заданной операцией *. Поэтому, если исходная коллекция была составлена ​​из '[Test1, Test2, Test2]', результатом будет '[Test2]' – dcastro

+1

Он хочет удалить все «Test1» из 'one' и добавить их в' two'. Так что на самом деле он хочет их перевести. –

0

В качестве примера решения, не LINQ, кажется, что это работает достаточно хорошо:

List<string> one = new List<string>(new[] {"Test 1", "Test 1", "Test 2"}); 
List<string> two = new List<string>(); 
var toRemove = new List<string>(); 

foreach (var value in one) 
{ 
    if(value.Equals("Test 1")) 
    { 
     toRemove.Add(value); 
     two.Add(value); 
    } 
} 

foreach (var value in toRemove) 
{ 
    one.Remove(value); 
} 
+2

Пожалуйста, объясните свои голоса. –

+0

Я полностью осознаю, что это не «самый гладкий» ответ, но все же ... это недействительно? –

+1

Я должен пойти с @roryap на этом. Помимо соглашения об именовании, это все еще решение для получения результата, который выполняет OP. –

0

Попробуйте

 List<string> two = (from i in one 
          where i.Contains("Test 1") 
          select i).ToList(); 

     one = one.Except(two).ToList(); 

Или более кратко:

List<string> two = one.Where(i => i.Contains("Test 1")).ToList(); 
one = one.Except(two).ToList(); 
1

Если вы хотите проверить эту строку:

string match = "Test1"; 

затем использовать это:

two.AddRange(one.Where(x => x == match)); 

разместить все соответствующие записи из списка one в список two.

Затем используйте:

one.RemoveAll(x => x == match); 

удалить все соответствующие записи из списка one.

0

Я хотел бы сделать что-то вроде этого:

//set string to match 
string match = "Test 1"; 
//check each item in the list 
for(int i =0; i<one.Count;i++) 
    { 
    if (one[i].Equals(match)) //see if it matches 
     { 
     int index = one.IndexOf(match);//get index of the matching item 
     one.RemoveAt(index);//remove the item 
     two.Add(match);//add the item to the other list 
     } 
    } 
1

как об этом?

two.AddRange(one.FindAll(x => x.Contains("Test 1"))); 
one.RemoveAll(x => two.Contains(x)); 

Следующий код

List<string> one = new List<string>(); 
List<string> two = new List<string>(); 

one.Add("Test 1"); 
one.Add("Test 1"); 
one.Add("Test 2"); 

two.AddRange(one.FindAll(x => x.Contains("Test 1"))); 
one.RemoveAll(x => two.Contains(x)); 

Console.WriteLine("ONE:"); 
foreach (string s in one) 
{ 
    Console.WriteLine(s); 
} 
Console.WriteLine("TWO:"); 
foreach (string s in two) 
{ 
    Console.WriteLine(s); 
} 
Console.ReadLine(); 

должно привести к

ONE: 
Test 2 
TWO: 
Test 1 
Test 1 
0

Попробуйте это:

two = one.FindAll(x => x.Contains("Test 1"); 
one.RemoveAll(x => x.Contains("Test 1"); 
+1

Рассмотрите возможность добавления объяснения того, как этот код будет решать проблему лучше, чем существующие ответы. Как правило, ответы с пояснениями оцениваются выше, чем без. –

0

Sequences имеет метод для данного конкретного случая использования, Sequence<T>.Partition.

var lists = one.AsSequence().Partition(x => x == "Test1"); 

var withTestOne = lists.Item1; 
var withoutTestOne = lists.Item2; 
0

Другим вариантом было бы использовать пункт GroupBy. Ниже я представил демонстрацию. Я включил как метод для получения определенного элемента (например, тест 1), так и метод перемещения всех существующих дубликатов. (Смотрите комментарии кода для более подробно.)

class Program 
{ 
    static List<string> _firstList; 
    static List<string> _secondList; 

    static void Main(string[] args) 
    { 
     // Initialize test values 
     Setup(); 

     // Display whats presenting in list 1. 
     Display(); 

     // Fill list 2 with all items in list 1 where the item is a value and remove the item 
     // from list 1. 
     FillListTwoWithSpecificValue("Test 1"); 

     /* Uncomment the line below if you want to populate list 2 with all duplicate items 
        while removing them from list 1.*/ 
     // FillListWithAllDuplicates(); 

     // Display the results after changes to list 1 and list 2 have been applied. 
     Display(); 

     Console.ReadLine(); 
    } 

    // Bonus method. Fills list 2 with any instance of a duplicate item pre-existing in list 1 while removing the item from the list. 
    static void FillListTwoWithAllDuplicates() 
    { 
     // Group the items in the first list 
     var duplicates = _firstList 
      .GroupBy(item => item) 
      .Where(g => g.Count() > 1) 
      .SelectMany(grp => grp); 

     // Iterate through each duplicate in the group of duplicate items and add them to the second list and remove it from the first. 
     foreach (var duplicate in duplicates) 
     { 
      _secondList.Add(duplicate); 

      // Remove all instances of the duplicate value from the first list. 
      _firstList.RemoveAll(item => item == duplicate); 
     } 
    } 

    // Fill list 2 with any instance of a value provided as a parameter (eg. Test 1) and remove the same value from list 1. 
    static void FillListTwoWithSpecificValue(string value) 
    { 
     // Group the items in the first list, and select a group according to the value provided. 
     var duplicates = _firstList 
      .GroupBy(item => item) 
      .SelectMany(grp => grp.Where(item => item == value)); 

     // Iterate through each duplicate in the group of duplicate items and add them to the second list and remove it from the first. 
     foreach (string duplicate in duplicates) 
     { 
      _secondList.Add(duplicate); 

      // Remove all instances of the duplicate value from the first list. 
      _firstList.RemoveAll(item => item == duplicate); 
     } 
    } 

    // Simply a method to initialize the lists with dummy data. This is only meant to keep the code organized. 
    static void Setup() 
    { 
     // Initialize lists 
     _firstList = new List<string>() 
     { 
      "Test 1", 
      "Test 1", 
      "Test 2", 
      "Test 3", 
      "Test 3", 
      "Test 4", 
      "Test 4", 
      "Test 5", 
      "Test 6", 
     }; 

     _secondList = new List<string>(); 
    } 

    // Simply a method to display the output to the console for the purpose of demonstration. This is only meant to keep the code organized. 
    static void Display() 
    { 
     // Checking to see if the second list has been populated. If not, lets just display what's in list 1 
     // since no changes have been made. 
     if (_secondList.Count == 0) 
     { 
      // Display the list 1 values for comparison. 
      Console.WriteLine("Items contained in list 1 before items moved to list 2:\n------------------------------------"); 
      foreach (var item in _firstList) 
      { 
       Console.WriteLine(item); 
      } 
     } 
     else 
     { 
      Console.WriteLine("\nItems now in list 1 after duplicates being removed:\n------------------------------------"); 
      foreach (var item in _firstList) 
      { 
       Console.WriteLine(item); 
      } 

      Console.WriteLine("\nItems now in list 2:\n------------------------------------"); 
      foreach (var item in _secondList) 
      { 
       Console.WriteLine(item); 
      } 
     } 
    } 
} 

Результаты будут распределены следующим образом:

Items contained in list 1 before items moved to list 2: 
------------------------------------ 
Test 1 
Test 1 
Test 2 
Test 3 
Test 3 
Test 4 
Test 4 
Test 5 
Test 6 

Items now in list 1 after duplicates being removed: 
------------------------------------ 
Test 2 
Test 3 
Test 3 
Test 4 
Test 4 
Test 5 
Test 6 

Items now in list 2: 
------------------------------------ 
Test 1 
Test 1