1

I got a lot of data from a database, which are results from a search function. Now I've a List<string[]> which has duplicated elements of type string[]. The string[] in the list are the search results.

I know that every new created array has a different instance so i can't use MyListOfArrays.Distinct().ToList().

Maybe it's a very basic question...

My question is, are there any functions built in to remove a duplicated string[] form the List<string[]>? Or do I have to write it by my selfe?

Thank you

5
  • 7
    You can use .Distinct() with a custom EqualityComparer: stackoverflow.com/questions/4607485/… Commented Oct 1, 2013 at 14:18
  • 6
    While not a direct answer to your question, it may be better to modify the query from the database so it does not give you duplicate results in its result set. Commented Oct 1, 2013 at 14:19
  • This is poorly not possible. I just call an api function. I wrote a loop because the api alows only one search field and I need to search in more the one field. This is why there are duplicates.. Commented Oct 1, 2013 at 14:26
  • Do you need to remove whole duplicate list or do you need to remove duplicated strings only? Commented Oct 1, 2013 at 14:31
  • The whole duplicate. It's every time an array with the same values. Commented Oct 1, 2013 at 14:34

3 Answers 3

3

You can use distinct method with custom equalityComparer

    IEnumerable<string[]> distinct = inputStringArrayList.Distinct(new EqualityComparer());

EqualityComparer

class EqualityComparer : IEqualityComparer<string[]>
{
    public bool Equals(string[] x, string[] y)
    {
        if (x.Length != y.Length)
        {
            return false;
        }
        if (x.Where((t, i) => t != y[i]).Any())
        {
            return false;
        }
        return true;
    }

    public int GetHashCode(string[] obj)
    {
        return obj.GetHashCode(); 
    }
}

Alternative Equals Method

public bool Equals(string[] x, string[] y)
{
    return x.SequenceEqual(y);
}

Here I am assuming you are having exact same string arrays with same content at same index.

Correction from Matthew Watson

public int GetHashCode(string[] obj)
        {
            if (obj == null)
                return 0;

            int hash = 17;

            unchecked
            {
                foreach (string s in obj)
                    hash = hash*23 + ((s == null) ? 0 : s.GetHashCode());
            }

            return hash;
        }
Sign up to request clarification or add additional context in comments.

8 Comments

I'm afraid this doesn't work, because the GetHashCode() returns different values even for identical sequences.
Is GetHashCode implemented in Array class?
Yes i got the same list after I implemented this function.
Use this: public int GetHashCode(string[] obj) { int hash = 17; foreach (string s in obj) hash = hash*23 + s.GetHashCode(); return hash; }
@MatthewWatson Check for null values too.
|
2

I have corrected the answer from @Muctadir Dinar.

(He deserves credit for the answer - I am just correcting it and providing a complete test program):

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    sealed class EqualityComparer: IEqualityComparer<string[]>
    {
        public bool Equals(string[] x, string[] y)
        {
            if (ReferenceEquals(x, y))
                return true;

            if (x == null || y == null)
                return false;

            return x.SequenceEqual(y);
        }

        public int GetHashCode(string[] obj)
        {
            if (obj == null)
                return 0;

            int hash = 17;

            unchecked
            {
                foreach (string s in obj)
                    hash = hash*23 + ((s == null) ? 0 : s.GetHashCode());
            }

            return hash;
        }
    }

    class Program
    {
        private void run()
        {
            var list = new List<string[]>
            {
                strings(1, 10), 
                strings(2, 10), 
                strings(3, 10), 
                strings(2, 10), 
                strings(4, 10)
            };

            dump(list);
            Console.WriteLine();

            var result = list.Distinct(new EqualityComparer());
            dump(result);
        }

        static void dump(IEnumerable<string[]> list)
        {
            foreach (var array in list)
                Console.WriteLine(string.Join(",", array));
        }

        static string[] strings(int start, int count)
        {
            return Enumerable.Range(start, count)
                .Select(element => element.ToString())
                .ToArray();
        }

        static void Main(string[] args)
        {
            new Program().run();
        }
    }
}

11 Comments

Very nice. Thank you this works. Edit: Accepted Muctadir Dinar's answer.
@Patrick Why would you accept a completely incorrect answer with several major errors that prevent it from working and would require non-trivial changes to fix?
@Servy My fault for saying "he deserves credit for the answer" I think. ;) I said that because didn't want to "steal" the idea of providing an IEqualityComparer implementation.
@Servy I just followed the sugestion of Metthew Watson, which he wrote in the second line of his post.
You should surround the foreach in getHashCode with unchecked. stackoverflow.com/a/263416/284240
|
1

A simple and not very efficient approach would be to use string.Join on the string[]:

list = list
.GroupBy(strArr => string.Join("|", strArr))
.Select(g => g.First())
.ToList();

3 Comments

This can have problems if the strings have | values in them. According to this {"a|b"} is equal to {"a", "b"}.
@Servy: Yes, that's what i meant with simple. Might be sufficient or not. So if the input is not arbitrary you could chose a separator that cannot occur.
My point is that it's not just slow. If it was always correct but possibly slow you need only be concerned with large amounts of data. When it's not always correct it's a much bigger concern as to whether or not it can be used in any given case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.