C# Using array.Where in Arraylist - c#

I have sets of codes in C# with array and I need to split the array into smaller size array.
I have no errors when declaring the array with :
List<int> array = new List<int>();
However, the code execution prompts out error at the array.Where when I declare as :
var array = new ArrayList();
Is there any way I can use array.Where in array list? Below is my code :
List<int> array = new List<int>();
for (int i = 0; i <=20; i++){
if (unitIsPresent)
{
array.add(1);
}
else
{
array.add(0)
}
}
devidedArray = array.Where((e, i) => i >= 5 && i < 10).ToArray();

Array List is a non generic collection type so it's good to store items in array where you don't consider the items types. So for this reason you can't use Linq methods that are used for generics collections like Where.
My recommendation is use a List and convert it to Array with the Linq method provided.this way is very fast.

If you really want to use an ArrayList (really? why?), you can use OfType<int>() to change the IEnumerable to an IEnumerable<int>.
var devidedArray = array.OfType<int>().Where((e, i) => i >= 5 && i < 10).ToArray();
Alternatively you could use Cast<int>():
var devidedArray = array.Cast<int>().Where((e, i) => i >= 5 && i < 10).ToArray();
The difference between the two is that OfType() will silently ignore objects that cannot be cast to int while Cast() will fail with an InvalidCastException.

https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=net-5.0
look microsoft doc.
We don't recommend that you use the ArrayList class for new development. Instead, we recommend that you use the generic List class. ...
just use List<T> to replace ArrayList.

Related

How to Create A Merged Array from 3 Arrays with LINQ which is not zipped but based on Content Equality

I have three Arrays which should be merged into one result via Linq:
int?[] list1 = {0,1,2,3,4};
int?[] list2 = {2,3,4,5};
int?[] list3 = {3,4};
Result:
var result=
{
(0,null,null),
(1,null,null),
(2,2,null),
(3,3,3),
(4,4,4),
(null,5,null)
}
Let's start by defining our input in a little more generic terms: a list of a list of integers. Since we don't need to modify these collections, we'll use the simplest interface that gives us what we need, IEnumerable<T>. That means our input is going to be: IEnumerable<IEnumerable<int?>>. Our output is going to be the same.
So now, let's define a prototype for the method that will do the work:
public static IEnumerable<IEnumerable<int?>> Merge(IEnumerable<IEnumerable<int?>> source) { //... }
Immediately I've noticed something: we don't really need to use int? since all we care about is checking equality, and all types support that, so we can make this method generic, and support any type:
public static IEnumerable<IEnumerable<T>> Merge<T>(IEnumerable<IEnumerable<T>> source) { //... }
Now let's start with the implementation, first we will need to compute every distinct value from all the lists:
source.SelectMany(x=>x).Distinct()
Now, for each of those values we need to return a collection with an item for each item in the original 'super list':
source.SelectMany(x=>x).Distinct().Select(x=>source.Select(y=> //...
So what do we need in that final Select lambda? We have x as each distinct integer (or technically T), and y as each original collection. We want the value x if the y collection contains x, otherwise, null (or to allow value types too, default(T). We can do that with a ternary:
source.SelectMany(x=>x).Distinct().Select(x=>source.Select(y=>y.Contains(x)?x:default(T)));
Putting it all together:
public static IEnumerable<IEnumerable<T>> Merge<T>(this IEnumerable<IEnumerable<T>> source)
{
return source
.SelectMany(x=>x)
.Distinct()
.Select(x=>source
.Select(y=>y.Contains(x)?x:default(T)));
}
And you can call it like so:
int?[] list1 = {0,1,2,3,4};
int?[] list2 = {2,3,4,5};
int?[] list3 = {3,4};
var result = new []{ list1, list2, list3 }.Merge();
Console.WriteLine(string.Join(Environment.NewLine, result.Select(t=>string.Join(",", t))));
First put all your arrays into one:
var lists = new[] { list1, list2, list3 };
Now loop all possible numbers and check if check if they are contained in the appropriate arrays. If so, you can add that number to your result, otherwise add null:
var result = new List<List<int?>>();
for(int i = 0; i < 6; i++)
{
result.Add(new List<int?>());
for(int j = 0; j < 3; j++)
{
if(lists[j].Contains(i))
result[i].Add(i);
else
result[i].Add(null);
}
}
I suppose this is pretty straightforward. Doing this is linq will just overcomplicate things, looks ugly and is hard to debug and understand. I doubt it´s a good idea to do so.

Copy IEnumerables or ICollections into an EXISITING array entry-wise

I have two IEnumerables already filled and an array large enough to store all elements of both of them:
IEnumerable<int> foo = ... // contains some elements.
IEnumerable<int> bar = ... // contains some elements.
int[] array = ... // already existing. array.Length is at least foo.Count + bar.Count
I want to copy the elements of foo and bar into array. And I would like to be able to do this without creating new objects (like LINQ would do when calling Concat or ToArray). In my concrete scenario, I do not care about the order, as it will be sorted later. A way to achieve it is this:
int k = 0;
foreach (int i in foo)
array[k++] = i;
foreach (int i in bar)
array[k++] = i;
I would like to know if there is some built-in method that does the copying for me (for convenience purposes), similar to LINQ ToArray or Concat, but without needing to create new objects. Giving ranges as input would be nice, too. A method like below maybe?
// desired way:
foo.InsertIntoArray(0) // insert the elements of foo into array starting at index 0
bar.InsertIntoArray(foo.Count) // insert the elements of bar into array starting at index foo.Count
I know the Array.Copy method, but as far as I know, it only works to copy from array to array, not from IEnumerable to array. Is there something alike?
List<int> foo = new List<int> { 1, 2, 3 };
List<int> bar = new List<int> { 3, 4, 5 };
//This will give you all items from both collections
var array = Enumerable.Concat(foo, bar).ToArray(); // 1,2,3,3,4,5
var array = foo.Concat(bar).ToArray();
//This will give you all distinct items
var array = Enumerable.Union(foo, bar).ToArray(); //1,2,3,4,5
var array = foo.Union(bar).ToArray();
You can also:
List<int> result = new List<int>();
result.AddRange(foo);
result.AddRange(bar);
result.InsertRange(result.Count, foo);
result.InsertRange(result.Count, bar);
foo.AddRange(bar); //But was assuming you don't want to change the existing list
But Both InsertRange and AddRange reallocate the internal array - And I assume Concut/Union use these behind the scenes
If your IEnumerable object also implements ICollection, you can cast it to ICollection and use the CopyTo method provided by this interface, otherwise you can only write loops. I actually looked at the source code for Enumerable.ToArray, and that's what Microsoft does.

Arraylist in arraylist sorting

I have an arraylist. it keeps arraylists in it. For example;
ar1 -> {2,3,46,67} keeps 4 members.
ar2 -> {28,96,67} keeps 3 members.
ar2 -> {56,32,67,54,214} keeps 5 members.
Ar_main[0]= ar1
Ar_main[1]= ar2
Ar_main[2]= ar3
i want to sort ar_main order by count of members. i used bubble sort algorithm. but it didn't work, can't we sort arraylist like this method?
private void sortArrayToAscending(ArrayList ar)
{
ArrayList ar1,ar2;
for (int i = 0; i < ar.Count - 1; i++)
for (int j = 1; j < ar.Count - i; j++)
{
ar1 = (ArrayList)ar[j];
ar2 = (ArrayList)ar[j-1];
if (ar1.Count < ar2.Count)
{
ArrayList temp = ar2;
ar2=ar1;
ar1=temp;
}
}
}
There is a built-in Sort method in the ArrayList that does the sorting for you. What you have to provide is an IComparer implementation that compares the list, making their length the criteria:
public void ArrayListSort()
{
var list = new ArrayList();
list.Sort(new LengthComparer());
}
class LengthComparer : IComparer
{
public int Compare(object x, object y)
{
var a = x as ArrayList;
var b = y as ArrayList;
// check for null if you need to!
return a.Count.CompareTo(b.Count);
}
}
However, unless you're actually using .NET 1.1, I'd recommend that you use List<T> instead of ArrayList, and the LINQ OrderBy method. This is type-safe, and I'd consider it more idiomatic C# nowadays. On top of that, it's way shorter:
var typedList = new List<List<int>>();
var sortedList = typedList.OrderBy(i => i.Count).ToList();
Be aware that the former is an in-place sort (altering the original list), whereas the latter copies the result into a new list.
I'm not allowed to comment yet or else I would. C# contains a built in static method in the ArrayList class. It sorts using the QuickSort algorithm. You may want to give it a try and see if it helps.Microsoft API Documentation ArrayList.Sort()

'Cropping' a list in c#

Given a Generic IList of some type, which contains a number of items, is there any way of 'cropping' this list, so that only the fist x items are preserved, and the rest discarded?
If you can use Linq, it's just a matter of doing
// Extraact the first 5 items in myList to newList
var newList = myList.Take(5).ToList();
// You can combine with .Skip() to extract items from the middle
var newList = myList.Skip(2).Take(5).ToList();
Note that the above will create new lists with the 5 elements. If you just want to iterate over the first 5 elements, you don't have to create a new list:
foreach (var oneOfTheFirstFive in myList.Take(5))
// do stuff
The existing answers create a new list containing a subset of items from the original list.
If you need to truncate the original list in-place then these are your options:
// if your list is a concrete List<T>
if (yourList.Count > newSize)
{
yourList.RemoveRange(newSize, yourList.Count - newSize);
}
// or, if your list is an IList<T> or IList but *not* a concrete List<T>
while (yourList.Count > newSize)
{
yourList.RemoveAt(yourList.Count - 1);
}
you have a very simple way to:
IList<T> list = [...]; //initialize
IList<T> newList = new List<T>(max);
for (i=0; i<max; i++) newList.Add(list[i]);
Note: max MUST be less or equal then list length (otherwise you get IndexOutOfBoundsException)
If you need to do it just with the IList<T> interface, then something like this is the solution:
for (int i = list.Count - 1; i >= numberOfElementsToKeep; --i) {
list.RemoveAt(i);
}
Working backwards from the end of the list here, in order to avoid moving around data which will be deleted in subsequent loop iterations.

How can I convert a list<> to a multi-dimensional array?

I have the following method signature:
public void MyFunction(Object[,] obj)
I create this object:
List<List<Object>> obj = new List<List<Object>>;
Is there an easy way I can convert this to an Object[,]?
UPDATE:
The fact is I like to use Lists because I can easily add a new item. Is there a way I can declare my List<> object to fit this need? I know the number of columns in my Object[,] but not the number of rows.
No. In fact, these aren't necessarily compatible arrays.
[,] defines a multidimensional array. List<List<T>> would correspond more to a jagged array ( object[][] ).
The problem is that, with your original object, each List<object> contained in the list of lists can have a different number of objects. You would need to make a multidimensional array of the largest length of the internal list, and pad with null values or something along those lines to make it match.
You're not going to get a very simple solution for this (i.e. a few lines). LINQ/the Enumerable class isn't going to help you in this case (though it could if you wanted a jagged array, i.e. Object[][]). Plain nested iteration is probably the best solution in this case.
public static T[,] To2dArray(this List<List<T>> list)
{
if (list.Count == 0 || list[0].Count == 0)
throw new ArgumentException("The list must have non-zero dimensions.");
var result = new T[list.Count, list[0].Count];
for(int i = 0; i < list.Count; i++)
{
for(int j = 0; j < list[i].Count; j++)
{
if (list[i].Count != list[0].Count)
throw new InvalidOperationException("The list cannot contain elements (lists) of different sizes.");
result[i, j] = list[i][j];
}
}
return result;
}
I've included a bit of error handling in the function just because it might cause some confusing errors if you used it on a non-square nested list.
This method of course assumes that each List<T> contained as an element of the parent List is of the same length. (Otherwise you really need to be using a jagged array.)
Here is a solution using Linq's Aggregate extension.
Note that the below does not check, nor is concerned if it gets a jagged sub list, it uses the max size of all the sublists and fills in according to the current list. If that is a concern one could add a check to the if to check for the same count amongst all the sub lists.
public static T[,] To2DArray<T>(this List<List<T>> lst)
{
if ((lst == null) || (lst.Any (subList => subList.Any() == false)))
throw new ArgumentException("Input list is not properly formatted with valid data");
int index = 0;
int subindex;
return
lst.Aggregate(new T[lst.Count(), lst.Max (sub => sub.Count())],
(array, subList) =>
{
subindex = 0;
subList.ForEach(itm => array[index, subindex++] = itm);
++index;
return array;
} );
}
Test / Usage
var lst = new List<List<string>>() { new List<string>() { "Alpha", "Beta", "Gamma" },
new List<string>() { "One", "Two", "Three" },
new List<string>() { "A" }
};
var newArray = lst.To2DArray();
Result:
To be blunt, the answer is no, not easily.
Perhaps you would like to edit your question to give us more background about why these declarations are needed and we can help you with your root problem?
Re your update:
I assume you cannot change the function you need to pass this into.
I don't see why you cannot just use an object[,] to begin with. This is my recommendation.
I doubt this will help you in your situation, but it might make some of the array working easier on you to start with. Do you know about the .ToArray() method on a List?

Categories