Reputation: 153
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:
Here the Suggestion of user3185569:
Upvotes: 7
Views: 10975
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
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);
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
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
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
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);
Upvotes: 0