Meliss
Meliss

Reputation: 153

Check a List contains the same value multiple times

Problem

Check collection contains the same number multiple times.

If it does contain the same numbers more than once, then I want to keep the first number and give a new value to the rest of the numbers, which are the same as the first one.

list newFitnessList does contain These numbers:

0. 4054.230995  --> after code= 4054.230995
1. 4041.416004  --> after code= 4041.416004
2. 3926.227397  --> after code= 3926.227397
3. 4722.250903  --> after code= 4722.250903
4. 4722.250903  --> after code= 0
5. 4226.636776  --> after code= 4226.636776
6. 4061.499026  --> after code= 4061.499026
7. 3876.278254  --> after code= 3876.278254
8. 4041.416004  --> after code= 0
9. 4779.468077  --> after code= 4779.468077
10. 4226.636776  --> after code= 0
11. 3876.278254  --> after code= 0
12. 4779.468077  --> after code= 0
13. 3926.227397  --> after code= 0

To achieve the solution explained above I tried the following code, but nothing is happening. The Output of the list is the same as before:

public List<double> sortDoppelganger(List<double> inputFitnessList)
{
  List<double> newFitnessList = inputFitnessList.ToList();
  for(int i = 0; i < newFitnessList.Count; i++)
  {
    double Nothing=0;
    double actual = newFitnessList[i];
    for(int j = newFitnessList.Count-1; j >= 0; j--)
    {
      double next = newFitnessList[j];
      if(actual == next)
      {
        next = Nothing;
      }
    }
  }
  return newFitnessList;
}

I would really appreciate it if someone has any idea what's wrong with my code. And maybe it would be better not to hide, that I'm a newbie with programming.

After reading the explanations: I tried out two idea's explained. First one was the idea of @Tim Schmelter and the second idea was from @user3185569.

And here you can take a look at what i was tyring to achieve: enter image description here

Here the suggestion of Tim: enter image description here

Here the Suggestion of user3185569: enter image description here

Upvotes: 7

Views: 10975

Answers (5)

Tim Schmelter
Tim Schmelter

Reputation: 460108

You could use a HashSet<double> to find out if there's a duplicate:

public List<double> SortDoppelganger(List<double> inputFitnessList, double replacementValue = 0)
{
    HashSet<double> doppelgangerFinder = new HashSet<double>();
    for (int i = 0; i < inputFitnessList.Count; i++)
    {
        double value = inputFitnessList[i];
        bool istDoppelganger = !doppelgangerFinder.Add(value);
        if (istDoppelganger)
            inputFitnessList[i] = replacementValue;
    }
    return inputFitnessList;
}

This solution modifies the original list. If that's not desired create a copy at the beginning by using var newList = new List<double>(inputFitnessList).

For what it's worth, here is a generic extension method that works with any type:

public static List<T> ReplaceDuplicates<T>(this IEnumerable<T> sequence, T replacementValue)
{
    HashSet<T> duplicateFinder = new HashSet<T>();
    List<T> returnList = new List<T>();
    foreach (T item in sequence)
    {
        bool isDuplicate = !duplicateFinder.Add(item);
        returnList.Add(isDuplicate ? replacementValue : item);
    }
    return returnList;
}

Explanation: user3185569 is right, i have forgotten to mention what you've done wrong. The main problem is that you try to assign the replacement value to the local variable next:

double next = newFitnessList[j];
if(actual == next)
{
  next = Nothing;
}

It has nothing to do with value- or reference-types differences in this case. The only reason why this doesn't work is that you modify only the value of the variable. Not the value the variable was referencing before(newFitnessList[j]). The variable does not even know that it was linked to the list. It just knows the value to store. If it was a reference type the problem would be the same. By replacing it with another value the list won't be modifed at all.

To cut a long story short, this would fix the main problem:

double next = newFitnessList[j];
if(actual == next)
{
  newFitnessList[j] = Nothing;
}

Upvotes: 8

Zein Makki
Zein Makki

Reputation: 30022

Problems with your code:

1- next is a local value-Type variable, so you're actually changing nothing inside the list.

2- You need to skip the case where i == j or you'll get all your values as 0 (Item matching itself)

public static List<double> sortDoppelganger(List<double> inputFitnessList)
{
    List<double> newFitnessList = inputFitnessList.ToList();
    for (int i = 0; i < newFitnessList.Count; i++)
    {
        double Nothing = 0;
        double actual = newFitnessList[i];
        for (int j = newFitnessList.Count - 1; j >= 0; j--)
        {
            if (j == i)
                continue;

            double next = newFitnessList[j];
            if (actual == next)
            {
                newFitnessList[j] = Nothing;
            }
        }
    }
    return newFitnessList;
}

You may need to replace if (actual == next) with (Math.Abs(actual - next) < 0.0001) as you can't trust double with exact comparisons.

Usage:

var newList = sortDoppelganger(list);

Things to learn from your mistake:

When you write double next = newFitnessList[j]; you're actually copying the value at that index of the list to a local variable named next. Since the type is double (A Value-Type), changing next doesn't change anything inside your List.

However, if you're using a reference type (A Customer Class instead of double for example), changing the value of the properties of next would change them inside the list.

Upvotes: 2

Aguda Hassan
Aguda Hassan

Reputation: 1

public List<double> filterlist(List<double> lst)
        {
            List<double> lstDouble = new List<double>();

            for (int i = 0; i < lst.Count; i++)
            {
                if (lstDouble.Contains(lst[i]))
                {
                    lstDouble.Add(0);
                }
                else
                {
                    lstDouble.Add(lst[i]);
                }
            }
            return lstDouble;
        }

Upvotes: 0

user6522773
user6522773

Reputation:

private static IEnumerable<double> sortDoppelganger(List<double> doubles)
{
  var newList = new List<double>();
  foreach (var t in doubles)
  {
    newList.Add(newList.Contains(t) ? 0.0 : t);
  }
  return newList;
}

Upvotes: 0

user6438653
user6438653

Reputation:

Nothing is 0, so it is setting the List values to 0.

You can use this to check for duplicates:

bool areDduplicates = lstNames.GroupBy(n => n).Any(c => c.Count() > 1);

From here.

Upvotes: 0

Related Questions