How to remove int[] from List<int[]>? - c#

I'm quite new in using List as arrays in C#. So I've encounter a problem while using it.
I'm trying to removed an int[] (integer array) from a List<int[]> using the Remove but failed to removed the int[] from the List<int[]>.
here is the code:
List<int[]> trash = new List<int[]>()
{
new int[] {0,1},
new int[] {1,0},
new int[] {1,1}
};
int[] t1 = {0,1};
trash.Remove(t1);
Is it just a bug?
Or it doesn't recognize int[] ?

The problem is that every array type is a reference type and List removes items based on equality where equality for reference types is by default reference equality. That means, you have to remove the very same array as is in the list.
The following for example works perfectly well:
int[] t1 = {0,1};
List<int[]> trash = new List<int[]>()
{
t1,
new int[] {1,0},
new int[] {1,1}
};
trash.Remove(t1);

If you want to remove all the lists which have the same contents (in the same order) as a target list, you can do so using List.RemoveAll() along with Linq's SequenceEqual():
List<int[]> trash = new List<int[]>
{
new [] {0, 1},
new [] {1, 0},
new [] {1, 1}
};
int[] t1 = {0, 1};
trash.RemoveAll(element => element.SequenceEqual(t1));
Console.WriteLine(trash.Count); // Prints 2
This is very slow though. Better to use an index if you can.

Error is List of array uses reference type data. therefore please use the removeAt method of List like below:
List<int[]> trash = new List<int[]>()
{
new int[] {0,1},
new int[] {1,0},
new int[] {1,1}
};
trash.RemoveAt(0);
With RemoveAt you need to pass the index of integer array you want to remove from the list.

Your t1 variable is a new instance of the array. So it won't be equal to the first element in the list.
Try:
trash.Remove(trash[0]);
or
trash.RemoveAt(0);

The .Remove method looks the address of the element. If they are equal, then it removes. You should do like this.
int[] t1 = {0,1};
int[] t2 =new int[] {1,0};
int[] t3 =new int[] {1,1};
List<int[]> trash = new List<int[]>()
{
t1,t2,t3
};
trash.Remove(t1);

foreach(var x in trash)
{
if(x[0] == t1[0] && x[1] == t[1])
{
trash.Remove(x);
break;
}
}
this should work aswell

It is just because you are trying to remove item that is new.
Its address reference is different than the object that is already in list.That is why it is not remove.
Int is value type..
And Int[] is reference type..
So when you do it with Int list
List<int> trash = new List<int>(){ 1, 13, 5 };
int t1 = 13;
trash.Remove(t1);//it will removed
But for Int[]
List<int[]> trash = new List<int[]>()
{
new int[] {0,1},
new int[] {1,0},
new int[] {1,1}
};
var t1 = {0,1};
trash.Remove(t1);//t1 will not removed because "t1" address reference is different than the "new int[] {0,1}" item that is in list.
To remove-
trash.Remove(trash.Find(a => a.SequenceEqual(t1)));
SequenceEqual() Determines whether two sequences are equal by comparing the elements by using the default equality comparer for their type.

If you want to remove the exact sequence, but you don't have the possibility to remove the exact object (sequence coming out from elsewhere) you can search for the right sequence using a lambda expression or an anonymous method:
List<int[]> trash = new List<int[]>
{
new [] {0, 1},
new [] {1, 0},
new [] {1, 1}
};
int[] t1 = { 0, 1 };
//using anonymous method
trash.RemoveAll(delegate(int[] element) { return element.SequenceEqual(t1); });
//using lambda expression
trash.RemoveAll(element => element.SequenceEqual(t1));

Related

How to add List<T> items dynamically to IEnumerable<T>

Code
public static void Main()
{
List<int> list1 = new List<int> {1, 2, 3, 4, 5, 6 };
List<int> list2 = new List<int> {1, 2, 3 };
List<int> list3 = new List<int> {1, 2 };
var lists = new IEnumerable<int>[] { list1, list2, list3 };
var commons = GetCommonItems(lists);
Console.WriteLine("Common integers:");
foreach (var c in commons)
Console.WriteLine(c);
}
static IEnumerable<T> GetCommonItems<T>(IEnumerable<T>[] lists)
{
HashSet<T> hs = new HashSet<T>(lists.First());
for (int i = 1; i < lists.Length; i++)
hs.IntersectWith(lists[i]);
return hs;
}
As for the sample, I showed "list1" "list2" "list3", but I may have more than 50 lists that are generating each list using for each loop. How can I add programmatically each "list" to IEnumerable lists for comparing data of each list?
I tried many ways like conversion to list, Add, Append, Concat but nothing worked.
Is there any other best way to compare the N number of lists?
The output of Code: 1 2
You can create a list of lists and add lists to that list dynamically. Something like this:
var lists = new List<List<int>>();
lists.Add(new List<int> {1, 2, 3, 4, 5, 6 });
lists.Add(new List<int> {1, 2, 3 });
lists.Add(new List<int> {1, 2 });
foreach (var list in listSources)
lists.Add(list);
var commons = GetCommonItems(lists);
To find intersections you can use this solution for example: Intersection of multiple lists with IEnumerable.Intersect() (actually looks like that's what you are using already).
Also make sure to change the signature of the GetCommonItems method:
static IEnumerable<T> GetCommonItems<T>(List<List<T>> lists)
What you could do is allow the GetCommonItems method to accept a variable amount of parameters using the params keyword. This way, you avoid needing to create a new collection of lists.
It goes without saying, however, that if the amount of lists in your source is variable as well, this could be trickier to use.
I've also amended the GetCommonItems method to work like the code from https://stackoverflow.com/a/1676684/9945524
public static void Main()
{
List<int> list1 = new List<int> { 1, 2, 3, 4, 5, 6 };
List<int> list2 = new List<int> { 1, 2, 3 };
List<int> list3 = new List<int> { 1, 2 };
var commons = GetCommonItems(list1, list2, list3); // pass the lists here
Console.WriteLine("Common integers:");
foreach (var c in commons)
Console.WriteLine(c);
}
static IEnumerable<T> GetCommonItems<T>(params List<T>[] lists)
{
return lists.Skip(1).Aggregate(
new HashSet<T>(lists.First()),
(hs, lst) =>
{
hs.IntersectWith(lst);
return hs;
}
);
}
Alternate solution using your existing Main method.
EDIT: changed the type of lists to IEnumerable<IEnumerable<T>> as per comment in this answer.
public static void Main()
{
List<int> list1 = new List<int> { 1, 2, 3, 4, 5, 6 };
List<int> list2 = new List<int> { 1, 2, 3 };
List<int> list3 = new List<int> { 1, 2 };
var lists = new List<List<int>> { list1, list2, list3 };
var commons = GetCommonItems(lists);
Console.WriteLine("Common integers:");
foreach (var c in commons)
Console.WriteLine(c);
}
static IEnumerable<T> GetCommonItems<T>(IEnumerable<IEnumerable<T>> enumerables)
{
return enumerables.Skip(1).Aggregate(
new HashSet<T>(enumerables.First()),
(hs, lst) =>
{
hs.IntersectWith(lst);
return hs;
}
);
}
IEnumerable is immutable so you always should return an implementation of IEnumerable depending on your needs.
If I understand correctly you want to get common items of N lists. I would use LINQ for this.
My proposition:
1. make one list that contains all of the items. =>
var allElements = new List<int>();
var lists = new List<List<int>>();
foreach (list in lists)
allElements.AddRange(list);
Take items that are repetitive
allElements.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x).ToList();

Summing up a list of integer arrays using threads for each array in C# Console application

I have a List of int arrays. The list can be from 1 to 4 arrays.
I want to know how do i go about summing each array with individual threads and
placing the summed values into a new int array.
If the order of the new array is not important here you have a example
List<int[]> arraysList = new List<int[]>();
arraysList.Add(new int[] { 2, 3, 5 });
arraysList.Add(new int[] { 2, 3, 5, 9, 123, 5 });
arraysList.Add(new int[] { 3 });
arraysList.Add(new int[] { 9,8 });
ConcurrentBag<int> SummedValueOfEveryArray = new ConcurrentBag<int>();
Parallel.ForEach(arraysList, array =>
{
SummedValueOfEveryArray.Add(array.Sum());
});
//Your result
var result = SummedValueOfEveryArray.ToArray<int>();
//The sum of all arrays
var totalSum = SummedValueOfEveryArray.Sum();
This code will do what you ask. One side note however, this only parallelizes when .Net feels it could improve performance.
List<int[]> intlist = new List<int[]>();
int[] result = intlist.AsParallel().Select(arr => arr.Sum()).ToArray();
Given 1 to 4 arrays it may be that .Net never sees the point of parallelizing. But if you absolutely must you can force parallelization by using Parallel.For as shown below.
List<int[]> intlist = new List<int[]>();
int[] result = new int[intlist.Count];
Parallel.For(0, intlist.Count, i =>
{
result[i] = intlist[i].Sum();
});

How to access and re-format Jagged Array in C#

I have 2D array in c#, like this:
int[][] 2darray = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
how can I get one column as normal array, like
int[] array = 2darray[1][]; //example, not working
and have
int[] array = {3,4};
?
Thanks.
There are several reasons why your code can't compile
This way it works:
int[][] array2d = { new[]{ 1, 2 }, new[]{ 3, 4 }, new[]{ 5, 6 }, new[]{ 7, 8 } };
int[] array = array2d[0];
Problems:
2darray is not a valid variable name
The indexing is wrong
The initialization of the original array is wrong
EDIT:
As stated by #heltonbiker, if you require all elements of the first column, you can use this:
int[] col = array2d.Select(row => row[0]).ToArray();
For an array with two columns and four rows, you can use LINQ this way:
using System.Linq;
first_column = _2darray.Select(row => row[0]).ToArray();
Note that changing the first or second array will not change the other one.
You are confusing jagged arrays and multidimensional arrays in C#. While they are similar, there is a slight difference. Rows in a jagged array can have a different number of elements, while in a 2D-array they are of the same length. Therefore when working with jagged arrays you need to remember to write handling for a missing column element. I composed a sample console app below to show how both of them work - it uses 0 as a substitute for a missing element, but you can throw an error etc.:
using System.Collections.Generic;
namespace JaggedArrayExample
{
class Program
{
static void Main(string[] args)
{
//jagged array declaration
int[][] array1;
//jagged array declaration and assignment
var array2 = new int[][] {
new int[] { 1, 2 },
new int[] { 3, 4 },
new int[] { 5, 6 },
new int[] { 7, 8 }
};
//2D-array declaration
int[,] array3;
//2D-array declaration and assignment (implicit bounds)
var array4 = new int[,] {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
//2D-array declaration and assignment (explicit bounds)
var array5 = new int[4, 2] {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
//get rows and columns at index
var r = GetRow(array2, 1); //second row {3,4}
var c = GetColumn(array2, 1); //second column {2,4,6,8}
}
private static int[] GetRow(int[][] array, int index)
{
return array[index]; //retrieving the row is simple
}
private static int[] GetColumn(int[][] array, int index)
{
//but things get more interesting with columns
//especially if jagged arrays are involved
var retValue = new List<int>();
foreach (int[] r in array)
{
int ub = r.GetUpperBound(0);
if (ub >= index) //index within bounds
{
retValue.Add(r[index]);
}
else //index outside of bounds
{
retValue.Add(0); //default value?
//or you can throw an error
}
}
return retValue.ToArray();
}
}
}
try this, it should work
int[] array = array2d[1];
Change the name of the variable to array2d, you cannot have variable that starts with number, a variable can start with letter or underscore.

Merging arrays with common element

I want to merge arrays with common element. I have list of arrays like this:
List<int[]> arrList = new List<int[]>
{
new int[] { 1, 2 },
new int[] { 3, 4, 5 },
new int[] { 2, 7 },
new int[] { 8, 9 },
new int[] { 10, 11, 12 },
new int[] { 3, 9, 13 }
};
and I would like to merge these arrays like this:
List<int[]> arrList2 = new List<int[]>
{
new int[] { 1, 2, 7 },
new int[] { 10, 11, 12 },
new int[] { 3, 4, 5, 8, 9, 13 } //order of elements doesn't matter
};
How to do it?
Let each number be a vertex in the labelled graph. For each array connect vertices pointed by the numbers in the given array. E.g. given array (1, 5, 3) create two edges (1, 5) and (5, 3). Then find all the connected components in the graph (see: http://en.wikipedia.org/wiki/Connected_component_(graph_theory))
I'm pretty sure it is not the best and the fastest solution, but works.
static List<List<int>> Merge(List<List<int>> source)
{
var merged = 0;
do
{
merged = 0;
var results = new List<List<int>>();
foreach (var l in source)
{
var i = results.FirstOrDefault(x => x.Intersect(l).Any());
if (i != null)
{
i.AddRange(l);
merged++;
}
else
{
results.Add(l.ToList());
}
}
source = results.Select(x => x.Distinct().ToList()).ToList();
}
while (merged > 0);
return source;
}
I've used List<List<int>> instead of List<int[]> to get AddRange method available.
Usage:
var results = Merge(arrList.Select(x => x.ToList()).ToList());
// to get List<int[]> instead of List<List<int>>
var array = results.Select(x => x.ToArray()).ToList();
Use Disjoint-Set Forest data structure. The data structure supports three operations:
MakeSet(item) - creates a new set with a single item
Find(item) - Given an item, look up a set.
Union(item1, item2) - Given two items, connects together the sets to which they belong.
You can go through each array, and call Union on its first element and each element that you find after it. Once you are done with all arrays in the list, you will be able to retrieve the individual sets by going through all the numbers again, and calling Find(item) on them. Numbers the Find on which produce the same set should be put into the same array.
This approach finishes the merge in O(α(n)) amortized (α grows very slowly, so for all practical purposes it can be considered a small constant).

Converting array/matrix initialization code from C++ to C#

I am in the middle of converting C++ code to C#. I am having trouble with some C++ array static initialization. Consider the following piece of C++:
int Values[][32] = {
{}, {}, {1, 2, 3}, {1}
};
What this does is creates a matrix of 4x32 integers. I need to do same or similar in C# in as straightforward way as possible. I am looking to get either
static int[][] Values = {...};
...or
static int[,] Values = {...};
The thing is C# does not seem to allow array initialization with uneven sub-array sizes. Other than this, if one specifies new int[4,32] {...} then everything between curly braces must be of exactly 32 length. With C++ one can specify {1, 2, 3} and the compiler will fill in the rest of the missing array members with zeros.
[EDIT] I have tried using LINQ and got what I desire but it looks cumbersome.
In C# the size of your array initializer must match the declared size of the array. You do not need to declare the size if you would like to avoid duplication.
If you need all entries to be of the same size, you can do it with a little helper function Expand, like this:
static int[] Expand(int[] src, int size) {
var res = new int[size];
Array.Copy(src, res, src.Length);
return res;
}
static int[][] Values = new int[4][] {
Expand(new[] {1}, 32)
, Expand(new[] {1,2,3}, 32)
, Expand(new[] {1,2,3}, 32)
, Expand(new[] {1,2,3, 4, 5}, 32)
};
I deleted my previous answer and am adding another (less eloquent) one that should work.
// utility function you can put in a class
static int[] BuildArray32(params int[] values)
{
int[] retVal = new int[32];
Array.Copy(values, retVal, values.Length);
return retVal;
}
// array initializer code
int[][] Values = {
BuildArray32(),
BuildArray32(),
BuildArray32(1, 2, 3),
BuildArray32(1),
};
EDIT Or you could make a builder class :)
class MatrixBuilder
{
int width;
List<int[]> rows;
public MatrixBuilder(int width)
{
this.width = width;
this.rows = new List<int[]>();
}
public MatrixBuilder Add(params int[] row)
{
int[] wideRow = new int[width];
Array.Copy(row, wideRow, row.Length);
rows.Add(wideRow);
return this;
}
public int[][] ToMatrix()
{
return rows.ToArray();
}
}
int[][] Values2 = new MatrixBuilder(32)
.Add()
.Add()
.Add(1, 2, 3)
.Add(1)
.ToMatrix();
You can't do it in c#. you can either initialise the arrays all to zeros, then apply your known initial values afterwards:
int[][] initAll = new []
{
new int[32] ,
new int[32] ,
new int[32] ,
new int[32]
};
or initialize a jagged array:
int[][] initJagged = new[]
{
new[] {1, 3, 5, 7, 9},
new[] {1, 3, },
new[] {1, 3,0,0,0,0,},
new int[32]
};

Categories