将所有匹配项从一个列表复制到另一个列表

时间:2015-04-02 11:55:00

标签: c#

考虑以下代码

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

列表一包含3个字符串

Test 1
Test 1
Test 2

我如何匹配字符串Test 1并将每个匹配的字符串放在List two中,并从列表一中删除匹配的字符串,这样它只留下Test 2字符串

这是我到目前为止所拥有的

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

如果我使用AddRange(),则会将整个列表添加到列表中

10 个答案:

答案 0 :(得分:4)

Linq的任务也可以通过以下方式解决。

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

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

答案 1 :(得分:1)

如果你想检查这个字符串:

string match = "Test1";

然后使用它:

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

将列表one中的所有匹配记录放入列表two

然后,使用它:

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

从列表one中删除所有匹配的记录。

答案 2 :(得分: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

答案 3 :(得分:1)

因此,您要从one中删除所有“Test1”并将其添加到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);
    }
}

答案 4 :(得分: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);
}

答案 5 :(得分: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();

答案 6 :(得分: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
      }
  }

答案 7 :(得分:0)

试试这个:

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

答案 8 :(得分:0)

Sequences有针对此特定用例的方法Sequence<T>.Partition

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

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

答案 9 :(得分: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