Remove duplicate entries for 2D List in C# - c#

I'm trying to remove example duplicate entries from this 2D List.
I've already tried using the .Distinct().ToList() method as highlighted in answers for 1D Lists but it doesn't seem to work for me here.
My code so far:
List<List<float>> xyvertices = new List<List<float>>();
xyvertices.Add(new List<float>());
yvertices[0].Add(2);
xyvertices[0].Add(4);
for (int a = 1; a < 6; a++)
{
xyvertices.Add(new List<float>());
xyvertices[a].Add(a+1);
xyvertices[a].Add(a+3);
}
xyvertices = xyvertices.Distinct().ToList();
Console.WriteLine("count:" + xyvertices.Count + "\n");
for (int i =0; i<xyvertices.Count; i++)
{
Console.WriteLine(xyvertices[i][0]);
Console.WriteLine(xyvertices[i][1]);
Console.WriteLine();
}
Console.ReadLine();
The above code runs but nothing changes.
How can I make this work? Thanks

Distinct is comparing the Lists, and as the first two Lists are distinct, even though they contain the same two numbers, they are not Equal.
Your outer List is a list of x,y pairs so rather than code these as arbitrary Lists of floats, you can use a Tuple. For example:
List<(float, float)> xyvertices = new List<(float, float)>();
xyvertices.Add((2, 4));
for (int a = 1; a < 6; a++)
{
xyvertices.Add((a+1,a+3));
}
xyvertices = xyvertices.Distinct().ToList();
Console.WriteLine("count:" + xyvertices.Count + "\n");
for (int i = 0; i < xyvertices.Count; i++)
{
Console.WriteLine(xyvertices[i]);
Console.WriteLine();
}

You can use Linq GroupBy and gruop by first and second element as follows :
xyvertices = xyvertices.GroupBy(x=>new {first= x[0],second= x[1] })
.Select(x=>new List<float> { x.Key.first, x.Key.second })
.ToList();
Output :
count:5
2
4
3
5
4
6
5
7
6
8

Related

Numbers wont follow when shifting array to the left

Numbers can shift to the left => check.
Only the first number in the array follows, the rest disappears.
Example how it is right now:
Input array: 1 2 3 4 5 6
Input how many times to shift left: 3
Output: 4 5 6 1
How the Output should be: 4 5 6 1 2 3
Can someone help met with this probably simple solution which I can't find.
var str = Console.ReadLine();
int shift = Convert.ToInt32(Console.ReadLine());
var strArray = str.Split(' ');
var x = strArray[0];
for (var i = 0; i < strArray.Length - shift; i++)
{
strArray[i] = strArray[i + shift];
}
strArray[strArray.Length - shift] = x;
for (var i = 0; i <= strArray.Length - shift; i++)
{
Console.Write(strArray[i] + ' ');
}
You can use Linq to perform your shift, here is a simple method you can use
public int[] shiftRight(int[] array, int shift)
{
var result = new List<int>();
var toTake = array.Take(shift);
var toSkip = array.Skip(shift);
result.AddRange(toSkip);
result.AddRange(toTake);
return result.ToArray();
}
Here is quick fix for you. please check following code.
I shift element to left by 1 position you can change code as par your requirement.
Input array: 1 2 3 4 5 6
Input how many times to shift left: 1
Output : 2 3 4 5 6 1
int[] nums = {1, 2, 3, 4, 5, 6};
Console.WriteLine("\nArray1: [{0}]", string.Join(", ", nums));
var temp = nums[0];
for (var i = 0; i < nums.Length - 1; i++)
{
nums[i] = nums[i + 1];
}
nums[nums.Length - 1] = temp;
Console.WriteLine("\nAfter rotating array becomes: [{0}]", string.Join(", ", nums));
If this is only for strings and the wraparound is necessary I would suggest to use str.Substring(0,shift)
and append it to str.Substring(shift) (don't try to reinvent the weel)
(some info about the substring method: String.Substring )
otherwise the reason why it did not work is because you only saved the first value of the array instead of all the values you wanted to shift.
Do not save only the first value in the array
var x = strArray[0];
use
string[] x = new string[shift];
for (int i = 0; i < shift; i++)
{
x[i] = strArray[i];
}
instead so you collect all the values you need to add to the end.
EDIT: forgot the shifting
Shift the old data to the left
for (int i = 0; i < strArray.Length-shift; i++)
{
strArray[i] = strArray[i+shift];
}
And replace
strArray[strArray.Length - shift] = x;
for
for(int i = 0; i < x.Length; i++){
int newlocation = (strArray.Length - shift)+i;
strArray[newlocation] = x[i];
}
also replace the print loop for
Console.WriteLine(string.Join(" ", strArray));
its easier and makes it one line instead of three lines of code.
(also the docs for the Join function string.Join)

Comparing c# array to itself

I'm trying to solve whats probably an easy task, but I'm extremely new to this and don't quite have my head around working with arrays in a complex fashion. I'm trying to figure out if two inputs each corresponding numbers sum to the same number (for example with 123 and 321, 1+3 2+2 and 1+3 all equal 4).
The code I have so far has broken down each input into arrays, and I can sum those arrays into a third array, but I cant figure out how to check it with itself. Should I even bother with the 3rd array, and just figure out how to check the sums of the array in a loop?
public static void Main()
{
Console.Write("\n\n"); //begin user input
Console.Write("Check whether each cooresponding digit in two intigers sum to the same number or not:\n");
Console.Write("-------------------------------------------");
Console.Write("\n\n");
Console.Write("Input 1st number then hit enter: ");
string int1 = (Console.ReadLine());//user input 1
Console.Write("Input 2nd number: ");
string int2 = (Console.ReadLine());//user input 2
int[] numbers = new int[int1.ToString().Length]; //changing user inputs to strings for array
int[] numbers2 = new int[int2.ToString().Length];
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = int.Parse(int1.Substring(i, 1));//populating arrays
numbers2[i] = int.Parse(int2.Substring(i, 1));
}
int[] numbers3 = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++)
{
numbers3[i] = (numbers[i] + numbers2[i]);
}
}
}
You can create the collections on the fly...
bool isEqual = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()))
.Zip(Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString())),
(i, j) => new
{
First = i,
Second = j,
Total = i + j
})
.GroupBy(x => x.Total)
.Count() == 1;
The output will equal true if all elements add up to the same value...
Test cases:
Should succeed
12345
54321
Should fail
12345
55432
To understand the above query, lets break it up into sections.
// Here I'm just converting a string to an IEnumerable<int>, a collection of integers basically
IEnumerable<int> ints1 = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()));
IEnumerable<int> ints2 = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()));
// Zip brings together two arrays and iterates through both at the same time.
// I used an anonymous object to store the original values as well as the calculated ones
var zippedArrays = ints1.Zip(ints2, (i, j) => new
{
First = i, // original value from ints1
Second = j, // original values from ints2
Total = i + j // calculated value ints1[x] + ints2[x]
});
// if the totals are [4,4,4], the method below will get rid of the duplicates.
// if the totals are [4,3,5], every element in that array would be returned
// if the totals are [4,4,5], only [4,5] would be returned.
var distinctByTotal = zippedArrays.GroupBy(x => x.Total);
// So what does this tell us? if the returned collection has a total count of 1 item,
// it means that every item in the collection must have had the same total sum
// So we can say that every element is equal if the response of our method == 1.
bool isEqual = distinctByTotal.Count() == 1;
You're 99% of the way there already. Just lose the third array and check each individual sum in your final loop.
bool isOK = numbers.Length = numbers2.Length && numbers.Length > 0;
if(isOK)
{
int expectedSum = numbers[0] + numbers2[0];
for (int i = 1; i < numbers.Length; i++)
{
var sum = (numbers[i] + numbers2[i]);
if(sum != expectedSum)
{
isOK = false;
break;
}
}
}
Console.WriteLine(isOk ? "Good job." : "You got some learning to do.");

Duplicated elements from x array add into y array

I tried to find 2 or more same elements from array x and then that duplicate to add into new array Y
So if i have in x array number like: 2,5,7,2,8 I want to add numbers 2 into y array
int[] x = new int[20];
Random rnd = new Random();
int[] y = new int[20];
int counter = 0;
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 15);
for (int j=i+1; j< x.Length; j++)
{
if (x[i] == x[j])
{
y[counter] = x[i];
Console.WriteLine("Repeated numbers are " + y[counter]);
counter++;
}
else
{
Console.WriteLine("There is no repeated numbers, numbers that are in x are " + x[i]);
}
break;
}
}
But having problems with that, when it come to the if loop it doesn't want to proceed with executing if loop (even if condition is true)
If someone could give me some suggestion, that would be helpful, thank you
There are various logical errors in your use of for. You should work more on your logic, because while libraries can be learnt by rote, logical errors are more something that is inside you.
int[] x = new int[20];
Random rnd = new Random(5);
// You don't know the length of y!
// So you can't use arrays
List<int> y = new List<int>();
// First initialize
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 15);
}
// Then print the generated numbers, otherwise you won't know what numbers are there
Console.WriteLine("Numbers that are in x are: ");
for (int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i]);
}
// A blank line
Console.WriteLine();
// Then scan
for (int i = 0; i < x.Length; i++)
{
for (int j = i + 1; j < x.Length; j++)
{
if (x[i] == x[j])
{
y.Add(x[i]);
Console.WriteLine("Repeated numbers is " + x[i]);
}
}
}
// Success/failure in finding repeated numbers can be decided only at the end of the scan
if (y.Count == 0)
{
Console.WriteLine("There is no repeated numbers");
}
I've put some comments in the code (plus the changes)
And for debugging purpose, I suggest you use a fixed Random sequence. new Random(5) (or any other number) will return the same sequence every time you launch your program.
Note that if there are multiple repetitions of a number, like { 4, 4, 4 } then the y array will be { 4, 4 }
at first:
why do u use the 'break;' ?
second:
in the first for - loop u assign a random number to x[i]
but then in the nested second loop
u already ask x[j] to check for same values (but that doesn't exist yet)
there are so many ways to check if values are equal,
but i like your approach:
so what i would suggest:
make a for - loop and assign all the random numbers to int[] x
then think again how u can evaluate
x[0] = x[1] or x[2] or x[3] ...
Try to use Linq to find the duplicate in the Array
int[] x = new int[] { 2, 5, 7, 2, 8 };
int[] y;
var result = x.GroupBy(item => item)
.Select(grp => new { key = grp.Key, Count = grp.Count() });
y = result.Where(res => res.Count > 1).Select(res => res.key).ToArray();
int[] array = new int[5] {1,2,3,4,4};
List<int> duplitcateList = array.Where(x => array.Where(y => y == x).Count() > 1).Distinct().ToList();
or you can replace last line of above code with below.
List<int> duplitcateList = array.
GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
above code is using Linq.
suppose your first array (in question x) is array.
Linq will first check for all elements in to list which occur more then once, and select them distinctly and store it to duplicateList
if you need an array at the, you can simply convert this list to array by doing this,
int[] yArray = duplitcateList.ToArray();
Make use of linq in your code , as below
//first populate array x
var duplicates= xArray.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToArray();
linq query above make use of groupby and find duplicate i.e. element occuring more then one time in you array and then you select those element and return result
I think this will will be the most understandable solution without complicated extension methods:
int[] x = new int[20];
// there can be at most 10 duplicates in array of length of 20 :)
// you could use List<int> to easily add elements
int[] y = new int[10];
int counter = 0;
Random rnd = new Random();
// fill the array
for (int i = 0; i < x.Length; i++)
x[i] = rnd.Next(1, 15);
// iterate through distinct elements,
// otherwise, we would add multiple times duplicates
foreach (int i in x.Distinct())
// if the count of an elements is greater than one, then we have duplicate
if(x.Count(n => n == i) > 1)
{
y[counter] = i;
counter++;
}

C#, how to save frequency of elements from one array in another, two-dimensional array?

So here's my problematic code. When I try to pass an array with N arguments, let's say {2,1,2,2,5} in result I want to get two-dimensional secArray[element,frequency of the element]. The problem is I get more than that and in this particular case I get an array like this:
23
11
22
21
52
Console.WriteLine("Enter number of elements: ");
int n = int.Parse(Console.ReadLine());
int[] array = new int[n];
for (int i = 0; i < array.Length; i++)
{
Console.Write("Array[{0}]: ", i);
array[i] = int.Parse(Console.ReadLine());
}
//problematic code begins
int[,] secArray = new int[n,2];
for(int i = 0;i<n;i++)
{
for(int j = 0; j<n;j++)
{
if(array[i] == secArray[j,0])
{
secArray[j, 1] += 1;
}
else
{
secArray[i, 0] = array[i];
secArray[i, 1] = 1;
}
}
}
//problematic code ends
//printing - works good
Console.WriteLine("How many same elements?");
for (int row = 0; row < secArray.GetLength(0); row++)
{
for (int col = 0; col < secArray.GetLength(1); col++)
{
Console.Write(secArray[row, col]);
}
Console.WriteLine();
}
If anyone has a clue how to fix this I'll be really grateful. It frustrates me that I don't know where the actual problem lies.
The first problem concerns the very first statement.
int[,] secArray = new int[n,2];
You don't know how many unique elements you have in your array until you traverse it. You can't use n, because n is the total number of arguments, which can be greater than the number of unique elements.
Next, the nested for loops are very inefficient. Your algorithm traverses the array for every element in the array- so it will run in O(n^2) time.
Think: do you have to traverse the array more than once? Why not just use a hashtable (dictionary in C#) to keep track of counts as you traverse the array? A hashtable uses a very efficient lookup mechanism to tell you if you've already seen the element, and the value can be used to keep track of count.
Consider replacing your problematic code with the following, and understanding how it works.
Dictionary<int, int> elementCounts = new Dictionary<int, int>();
for(int i = 0; i < n; i++)
{
int element = array[i];
if (elementCounts.ContainsKey(element))
elementCounts[element]++;
else
elementCounts.Add(element, 1);
}
Console.WriteLine("How many same elements?");
foreach(KeyValuePair<int,int> count in elementCounts)
{
Console.WriteLine("Element: {0} Count: {1}", count.Key, count.Value);
}
Then, if you want to copy the results in the hashtable (Dictionary) to a two-dimensional array, you can do the following.
int numberOfUniqueElements = elementCounts.Count;
int[,] secArray = new int[numberOfUniqueElements, 2];
int j = 0;
foreach (KeyValuePair<int, int> count in elementCounts)
{
secArray[j, 0] = count.Key;
secArray[j, 1] = count.Value;
j++;
}
I would use Linq's GroupBy to do this
var array = new int[] { 2, 1, 2, 2, 5 };
var result = array.GroupBy(x => x).Select(x => new[] { x.Key, x.Count() }).ToArray();
Why don't you use a hash table. Let the number in the array be the hash entry key, and let the value of the hash entry be the count. Then just iterate through the array once. While iterating through the array check if hash entry exists if so add 1 to it, if not create it.
Something like
for(int i = 0; i<n;i++) {
if(hashTable.containsKey(array[i])) {
hashTable[array[i]]++];
} else {
hashTable.add(array[i],1);
}
}
Please note that this is quedocode and will require to lookup the methods and implement it correctly.

Array.IndexOf vs. value of given index issue

I'm trying to loop through a given array and find how many duplicate values I have inside it. It works by going through a nested loop checking all elements of the array against each other and making sure it doesn't rise the counter if it's on the same index. But the problem is, it never counts up!
Now it's either I don't understand the concept of valueOf vs indexOf or I'm just completely lost.
int[] myArr = new int[] { 10, 5, 5 };
int counter = 0;
for (int i = 0; i < myArr.Length; i++)
{
for (int j = 0; j < myArr.Length; j++)
{
if (Array.IndexOf(myArr, myArr[i]) == Array.IndexOf(myArr, myArr[j]))
{
continue;
}
else if (myArr[i] == myArr[j])
{
counter++;
}
}
}
Console.WriteLine("There are {0} repeating values in the array.", counter);
// Output: There are 0 repeating values in the array.
Array.IndexOf searches for the first occurrence of the value in the array.
It looks like in your example you are trying to use it to make sure you're not comparing the same position in the array. In which case you could just replace that condition with if(i == j)
Going along with the other answers/comments stating the Array.IndexOf is not the correct approach to this problem, and not exactly sure if you're allowed to use LINQ, but that is by far a better approach, especially using the GroupBy method.
I have created a dotnetfiddle for you to show what I am doing.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
int[] myArr = new int[] { 10, 5, 5, 3, 3, 3 };
// int counter = 0; - now this is no longer needed
var numbersThatAreDuplicates = myArr.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => new { number = x.Key, countOfNumber = x.Count()}).ToList();
Console.WriteLine("There are {0} repeating values in the array.", numbersThatAreDuplicates.Count);
foreach (var item in numbersThatAreDuplicates)
{
Console.WriteLine(item.number + " repeats itself " + item.countOfNumber + " times.");
}
}
}
// Output
// There are 2 repeating values in the array.
// 5 repeats itself 2 times.
// 3 repeats itself 3 times.
As you can see, via the GroupBy method, you can find out how many numbers are repeating, as well as what the actual numbers are along with the number of occurrences that the actual number repeats itself in 1 line of code. Much cleaner, and efficient than using nesting for loops, but again I am not sure of what your limitations are.
I hope this helps.
You don't need to use the Array.IndexOf() function.
for example:
int[] myArr = new int[] { 10, 5, 5, 5};
int counter = 0;
List<int> dups = new List<int>();
for (int i = 0; i < myArr.Length; i++)
{
for (int j = 0; j < myArr.Length; j++)
{
if (i != j && myArr[i] == myArr[j] && !dups.Contains(i))
{
dups.Add(j);
counter++;
}
}
}
Console.WriteLine("There are {0} repeating values in the array.", counter);
// Output: There are 2 repeating values in the array.

Categories

Resources