Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1048
  • Last Modified:

compare two two generic list of strings

Dear experts:
Please help to implement the following two generic list of strings comparison:
Input: Two lists: cs1 and cs2 (List<string>)
Logic: Method must compare both cs1 and cs2 as follows:
If a string is in cs1 but not in cs2 then add string to Added list.
If a string is in not in cs1 but it is in cs2 then add string to Deleted list.
If a string is in both cs1 and cs2 then ignore it.

Output: Two lists: Added and Deleted  as List<string>

The answer could be written as a method in C# or VB.NET. Input list sizes can vary from 3 to 280 items.

e.g. cs1: abc, def, fgh
cs2: abc, xyz
Added: def, fgh.
Deleted:  xyz.

Thanks,

mas
0
Miguel Oz
Asked:
Miguel Oz
  • 3
  • 3
  • 2
  • +1
3 Solutions
 
louisfrCommented:
The Except extension method is what you need:
List<string> Added = cs1.Except(cs2).ToList();
List<string> Deleted = cs2.Except(cs1).ToList();

Open in new window

0
 
Jean Marie GeeraertsApplication EngineerCommented:
louisfr is correct.
Here's a complete code example of how to use an extension method with generic IEnumerables.

This is in a console application where the extension method is called directly from Program.cs
The example demonstrates for both a list of strings and a list of integers using the same generic method.
using System;
using System.Collections.Generic;

namespace EE
{
    class Program
    {
        static void Main(string[] args)
        {
            CompareTwoStringLists();
            Console.Clear();
            CompareTwoIntegerLists();
        }

        private static void CompareTwoStringLists()
        {
            var cs1 = new[] {"abc", "def", "fgh"};
            var cs2 = new[] {"abc", "xyz"};

            IEnumerable<string> added;
            IEnumerable<string> deleted;

            cs1.FindAddedAndDeleted(cs2, out added, out deleted);

            string addedOutput = string.Join(",", added);
            string deletedOutput = string.Join(",", deleted);

            Console.WriteLine("Added: {0}", addedOutput);
            Console.WriteLine("Deleted: {0}", deletedOutput);
            Console.WriteLine();
            Console.WriteLine("Press a key to continue");
            Console.ReadKey();
       }

        private static void CompareTwoIntegerLists()
        {
            var ci1 = new[] { 1, 2, 3 };
            var ci2 = new[] { 2, 3, 4 };

            IEnumerable<int> addedIntegers;
            IEnumerable<int> deletedIntegers;

            ci1.FindAddedAndDeleted(ci2, out addedIntegers, out deletedIntegers);

            Console.Write("Added: ");
            foreach (var addedInteger in addedIntegers)
            {
                Console.Write("{0} ", addedInteger);
            }
            Console.WriteLine();
            Console.Write("Deleted: ");
            foreach (var deletedInteger in deletedIntegers)
            {
                Console.Write("{0} ", deletedInteger);
            }
            Console.WriteLine();
            Console.WriteLine("Press a key to continue");
            Console.ReadKey();

        }
    }
}

Open in new window

This is the static class that holds the extension method:
using System.Collections.Generic;
using System.Linq;

namespace EE
{
    public static class GenericExtensions
    {
        public static void FindAddedAndDeleted<T>(this IEnumerable<T> list, IEnumerable<T> original, out IEnumerable<T> added, out IEnumerable<T> deleted)
        {
            var first = list as IList<T> ?? list.ToList();
            var second = original as IList<T> ?? original.ToList();
            added = first.Except(second);
            deleted = second.Except(first);
        }

        public static void FindAddedAndDeleted(this IEnumerable<object> list, IEnumerable<object> compareToList, out IEnumerable<object> added, out IEnumerable<object> deleted)
        {
            var first = list as IList<object> ?? list.ToList();
            var second = compareToList as IList<object> ?? compareToList.ToList();
            added = first.Except(second);
            deleted = second.Except(first);
        }
    }
}

Open in new window

The static class uses a generic method so you can compare any IEnumerable object.
0
 
it_saigeDeveloperCommented:
As louis pointed out, you can use Except.  Jean also provides a great example (although, you need to convert the Enumerables added and deleted to arrays for the string.Join methods overloads).
using System;
using System.Collections.Generic;
using System.Linq;

namespace EE_Q28571938
{
	class Program
	{
		static void Main(string[] args)
		{
			CompareTwoStringLists();
			Console.Clear();
			CompareTwoIntegerLists();
		}

		private static void CompareTwoStringLists()
		{
			var cs1 = new[] { "abc", "def", "fgh" };
			var cs2 = new[] { "abc", "xyz" };

			IEnumerable<string> added;
			IEnumerable<string> deleted;

			cs1.FindAddedAndDeleted(cs2, out added, out deleted);

			string addedOutput = string.Join(",", added.ToArray());
			string deletedOutput = string.Join(",", deleted.ToArray());

			Console.WriteLine("Added: {0}", addedOutput);
			Console.WriteLine("Deleted: {0}", deletedOutput);
			Console.WriteLine();
			Console.WriteLine("Press a key to continue");
			Console.ReadKey();
		}

		private static void CompareTwoIntegerLists()
		{
			var ci1 = new[] { 1, 2, 3 };
			var ci2 = new[] { 2, 3, 4 };

			IEnumerable<int> addedIntegers;
			IEnumerable<int> deletedIntegers;

			ci1.FindAddedAndDeleted(ci2, out addedIntegers, out deletedIntegers);

			Console.Write("Added: ");
			foreach (var addedInteger in addedIntegers)
			{
				Console.Write("{0} ", addedInteger);
			}
			Console.WriteLine();
			Console.Write("Deleted: ");
			foreach (var deletedInteger in deletedIntegers)
			{
				Console.Write("{0} ", deletedInteger);
			}
			Console.WriteLine();
			Console.WriteLine("Press a key to continue");
			Console.ReadKey();

		}
	}

	static class Extensions
	{
		public static void FindAddedAndDeleted<T>(this IEnumerable<T> source, IEnumerable<T> comparer, out IEnumerable<T> added, out IEnumerable<T> deleted)
		{
			var first = source as IList<T> ?? source.ToList();
			var second = comparer as IList<T> ?? comparer.ToList();
			added = first.Except(second);
			deleted = second.Except(first);
		}
	}
}

Open in new window


Produces the following output -Capture.JPGCapture.JPG
-saige-
0
Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

 
louisfrCommented:
If using the Framework 4 or above, you don't need to produce an array.
String.Join has been added an overload taking an Enumerable.
0
 
it_saigeDeveloperCommented:
I should have been more specific with my correction of Jean's example.  :(  Thanks for the pickup louis.  ;)

Also, as a point of clarification to what I had stated above:

As louis pointed out, you *should* use... as opposed to, you *can* use...  With something like this, there is really no need to reinvent the wheel, as it were.

-saige-
0
 
Jean Marie GeeraertsApplication EngineerCommented:
Totally agree with above, no need to reinvent the wheel, so I used louisfr 's hint to provide the asker with a working example. As of such, if asker would consider my answer the one to help him/her, at least points would need to be divided as I only extended the solution provided by louisfr!!

For the string.Join, this does indeed work with an IEnumerable in the latest .Net version and I did just put a quick string.Join in the example for a nice UI output in the console application, how the result is presented is of course up to the requirements.

For the int version I didn't bother to use a stringbuilder or whatever, after all it's just a quick and dirty demo application :-)

Big advantage of the generic extension is that you can use it on any IEnumerable and immediately get the two IEnumerables for added/deleted lists. Otherwise it just uses what .Net has available through linq.
0
 
it_saigeDeveloperCommented:
@Jean, it was not my intent to make it seem as if you were reinventing the wheel.  I hope you did not take it that way.  As for points; I expect no points from this, just ensuring the the author was provided a visual example of the output.

-saige-
0
 
Miguel OzSoftware EngineerAuthor Commented:
Thanks
0
 
Jean Marie GeeraertsApplication EngineerCommented:
Hi it_saige, no worries. I didn't take it that way. Just clarified my example a bit further and wanted to point out that I agreed with the proposed solution and just elaborated on it, thus making sure the correct expert (=louisfr) got his recognition :-)
0

Featured Post

Fill in the form and get your FREE NFR key NOW!

Veeam is happy to provide a FREE NFR server license to certified engineers, trainers, and bloggers.  It allows for the non‑production use of Veeam Agent for Microsoft Windows. This license is valid for five workstations and two servers.

  • 3
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now