How to convert a List to IEnumerable? - c#

I was solving a problem which needs to write a function that returns only the integers from an object List(I have written the function but it doesn't work). I have thought for a long time how to convert the List to IEnumerable, I was searching how to solve the problem, but I haven't found the right solution yet. Please, can anyone help me with this, maybe easy, problem?
public static IEnumerable<int> GetIntegersFromList(List<object> listOfItems)
{
List<object> result = new List<object>();
for (int i = 0; i < listOfItems.Count - 1; i++)
{
if (listOfItems[i] is string)//the input is only integers and strings
{
listOfItems.RemoveAt(i);
}
}
return listOfItems;//this doesn't work
}

You don't convert a list to IEnumeruble<T> - a list is already an IEnumerable<T>. The problem in your code is that the list of objects is not an IEnumerable<int>.
You have three approaches to solving this:
Make a new List<int>, populate it in your loop, and return it, or
Use yield return to avoid constructing the list explicitly, or
Apply LINQ's OfType<int> to listOfItems to get the result in a single line of code.

As the other answer says, Linq is one way to go.
Here is a compact one liner method with out testing it.
public static IEnumerable<int> GetIntegersFromList(List<object> listOfItems)
{
return listOfItems.Where(i => i is int)).Select(i => (int) i).ToList();
}
It can even be shorter
return listOfItems.OfType<int>().ToList();
Thx to #Blake Thingstad and #mjwills for their input.

static void Main()
{
List<object> dd = new List<object>() { 1, 2, "a", "b", 8 };
var dd2 = new List<int>(GetIntegersFromList(dd));
dd2.ForEach(j => Console.Write("{0}\t", j));
Console.ReadKey();
}
public static IEnumerable<int> GetIntegersFromList(List<object> listOfItems)
{
return listOfItems.OfType<int>().ToList();
}

Related

Why List<int>.Remove() method removing entries from the calling method's list? [duplicate]

This question already has answers here:
List passed by ref - help me explain this behaviour
(8 answers)
Closed 7 years ago.
Pardon me if its a very foolish question. But I want to know why this is happening.
My code is
static void Main(string[] args)
{
List<int> lst = new List<int>();
for (int i = 0; i< 10; i++)
{
lst.Add(i);
}
List<int> lstRet = lst;
List<int> lstRet2 = lstReturn(lstRet);
}
static List<int> lstReturn(List<int> lst)
{
List<int> NewList = lst;
NewList.Remove(3);
NewList.Remove(6);
NewList.Remove(9);
return NewList;
}
The problem is after the method lstReturn(lstRet); is getting called, both the list Values values are same, as if lst and lstRet2 both are identical List.
Why it is like that. Can anybody please explain? Is only one copy of List is created, if yes, why?
I am again saying if its a duplicate, pardon me, I searched but didn't get any satisfactory answer.
Thanks
Edit:
The question was not a duplicate, the solution lies elsewhere, may be the fundamental knowledge is same. Instead passing the same list lst to lstRet, if its like
List<int> lstRet = New List<int>(lst)
this solved the problem, Thanks to all of you for such a quick response.
The problem is with this line:
List<int> lstRet = lst;
It does not do what you want it to do - instead of copying the list, it copies the reference. You have only one list, from which the items get removed.
If you wish to make a copy, replace the line above with
List<int> lstRet = new List<int>(lst);
They are the same list. You are assigning the return value of lstReturn to the variable lstRet2:
List<int> lstRet2 = lstReturn(lstRet);
and the function lstReturn returns the list that was passed in:
static List<int> lstReturn(List<int> lst)
{
List<int> NewList = lst; // NewList now is the list that was passed in
// snip...
return NewList;
}

Convert List<string> to List<int> in C#

I want to convert a List<string> to a List<int>.
Here is my code:
void Convert(List<string> stringList)
{
List<int> intList = new List<int>();
for (int i = 0; i < stringList.Count; i++)
{
intList.Add(int.Parse(stringList[i]));
}
)
Instead of using LINQ you can use List<T>.ConvertAll<TOutput>(...)
List<int> intList = stringList.ConvertAll(int.Parse);
I would suggest using TryParse(), in case some of the values are not convertible into int.
For this I have created an Extension Method. Below is my demo LinqPad code.
void Main()
{
List<string> sourceList = new List<string> {"1", "2","3", "qwert","4", "5","6", "7","asdf", "9","100", "22"};
//Dump is a LinqPad only method. Please ignore
sourceList.ConvertToInt().Dump();
}
static public class HelperMethods
{
static public List<int> ConvertToInt(this List<string> stringList)
{
int x = 0;
var intList = stringList.Where(str => int.TryParse(str, out x))
.Select (str => x)
.ToList();
return intList;
}
}
In this case, only the numeric int values get parsed and the rest is gracefully ignored. You could built in some error handling / notification if you want to.
/Edit
Based on Peter Kiss' suggestion here is a more generic approach based on the IEnumerable interface.
static public IEnumerable<int> ConvertToInt(this IEnumerable<string> source)
{
int x = 0;
var result = source.Where(str => int.TryParse(str, out x))
.Select (str => x);
return result;
}
With this you'd just have to call AsEnumerable() before calling ConvertToInt() The result is of course of type IEnumerable<Int32> and from here on, you can convert it easily into a List by using .ToList() or an array or whatever you need at that point.
With Linq:
var intList = stringList.Select(x => int.Parse(x)).ToList();
Use the following code:
int x = 0;
var intList= stringList.Where(str => int.TryParse(str, out x)).Select(str => x).ToList();
If you don't want to use Linq (which I always find hard to understand), your code looks right, but of course you need to return something:
List<int> Convert(List<string> stringList)
{
List<int> intList = new List<int>();
for (int i = 0; i < stringList.Count; i++)
{
intList.Add(int.Parse(stringList[i]));
}
return intList;
}
Be aware that this will throw an exception if the string list contains something that is not parseable as an int.
Edit:
Better yet, use a foreach loop:
List<int> Convert(List<string> stringList)
{
List<int> intList = new List<int>();
foreach(String s in stringList)
{
intList.Add(int.Parse(s));
}
return intList;
}
Thank you all of you. It's fantastic how much help one can get here!
I finally solved the problem by making the string list to an Array, and then converting the Array to int. Maybe not the brightest solution, but my code now works. I will try your suggestions later on to see if I can still use list instead of Array.
Thank you all of you!
Your method works fine, so I am assuming you are a beginner developer who is still learning the syntax of the language. I will not give you the advanced LINQ solution just yet, but help you achieve what you want with your current code. You are currently not returning the list you are creating, so change the method signature from:
void Convert(List<string> stringList)
to:
List<int> Convert(List<string> stringList)
and at the very end just before the method ends add:
return intList;
Then in your code you can call it like so:
List<string> strings = new List<string> { "1", "2", "3" };
List<int> integers = this.Convert(strings);
Note: If you don't want your code to throw an exception, might I suggest using TryParse instead of Parse, be careful however since this method works slightly differently and makes use of out parameters. You can learn more about it here.
If you are interested in LINQ, #Peter Kiss's solution is as good as it gets. He is using LINQ with method syntax, but there's also SQL-like syntax which you may or may not find easier to grasp. A good introduction to LINQ can be found here.
In case your stringList has a string that can't be parsed then you can mask that with a default error/invalid value of say -1, rather than encountering exception as below:
List<string> stringList = new List<string>();
stringList.AddRange(new string[] { "1", "2", "3", "4", "sdfsf", "7" }); // for illustration
int temp;
var yourIntegerList = stringList.Select(x => int.TryParse(x, out temp) ? int.Parse(x) : -1).ToList(); // -1 used here, can be any integer
// Now you may remove all -1's
yourIntegerList = yourIntegerList.Where(a => a != -1).ToList();

Convert an object array of object arrays to a two dimensional array of object

I have a third party library returning an object array of object arrays that I can stuff into an object[]:
object[] arr = myLib.GetData(...);
The resulting array consists of object[] entries, so you can think of the return value as some kind of recordset with the outer array representing the rows and the inner arrays containing the field values where some fields might not be filled (a jagged array). To access the individual fields I have to cast like:
int i = (int) ((object[])arr[row])[col];//access a field containing an int
Now as I'm lazy I want to access the elements like this:
int i = (int) arr[row][col];
To do this I use the following Linq query:
object[] result = myLib.GetData(...);
object[][] arr = result.Select(o => (object[])o ).ToArray();
I tried using a simple cast like object[][] arr = (object[][])result; but that fails with a runtime error.
Now, my questions:
Is there a simpler way of doing this? I have the feeling that some
nifty cast should do the trick?
Also I am worried about performance
as I have to reshape a lot of data just to save me some casting, so I
wonder if this is really worth it?
EDIT:
Thank you all for the speedy answers.
#James: I like your answer wrapping up the culprit in a new class, but the drawback is that I always have to do the Linq wrapping when taking in the source array and the indexer needs both row and col values int i = (int) arr[row, col]; (I need to get a complete row as well like object[] row = arr[row];, sorry didn't post that in the beginning).
#Sergiu Mindras: Like James, i feel the extension method a bit dangerous as it would apply to all object[] variables.
#Nair: I chose your answer for my implementation, as it does not need using the Linq wrapper and I can access both individual fields using int i = (int) arr[row][col]; or an entire row using object[] row = arr[row];
#quetzalcoatl and #Abe Heidebrecht: Thanks for the hints on Cast<>().
Conclusion: I wish I could choose both James' and Nair's answer, but as I stated above, Nair's solution gives me (I think) the best flexibility and performance.
I added a function that will 'flatten' the internal array using the above Linq statement because I have other functions that need to be fed with such a structure.
Here is how I (roughly) implemented it (taken from Nair's solution:
public class CustomArray
{
private object[] data;
public CustomArray(object[] arr)
{
data = arr;
}
//get a row of the data
public object[] this[int index]
{ get { return (object[]) data[index]; } }
//get a field from the data
public object this[int row, int col]
{ get { return ((object[])data[row])[col]; } }
//get the array as 'real' 2D - Array
public object[][] Data2D()
{//this could be cached in case it is accessed more than once
return data.Select(o => (object[])o ).ToArray()
}
static void Main()
{
var ca = new CustomArray(new object[] {
new object[] {1,2,3,4,5 },
new object[] {1,2,3,4 },
new object[] {1,2 } });
var row = ca[1]; //gets a full row
int i = (int) ca[2,1]; //gets a field
int j = (int) ca[2][1]; //gets me the same field
object[][] arr = ca.Data2D(); //gets the complete array as 2D-array
}
}
So - again - thank you all! It always is a real pleasure and enlightenment to use this site.
You could create a wrapper class to hide the ugly casting e.g.
public class DataWrapper
{
private readonly object[][] data;
public DataWrapper(object[] data)
{
this.data = data.Select(o => (object[])o ).ToArray();
}
public object this[int row, int col]
{
get { return this.data[row][col]; }
}
}
Usage
var data = new DataWrapper(myLib.GetData(...));
int i = (int)data[row, col];
There is also the opportunity to make the wrapper generic e.g. DataWrapper<int>, however, I wasn't sure if your data collection would be all of the same type, returning object keeps it generic enough for you to decide what data type cast is needed.
There are few similar answer posted which does something similar. This differ only if you want to acess like
int i = (int) arr[row][col];
To demonstrate the idea
public class CustomArray
{
private object[] _arr;
public CustomArray(object[] arr)
{
_arr = arr;
}
public object[] this[int index]
{
get
{
// This indexer is very simple, and just returns or sets
// the corresponding element from the internal array.
return (object[]) _arr[index];
}
}
static void Main()
{
var c = new CustomArray(new object[] { new object[] {1,2,3,4,5 }, new object[] {1,2,3,4 }, new object[] {1,2 } });
var a =(int) c[1][2]; //here a will be 4 as you asked.
}
}
(1) This probably could be done in short and easy form with dynamic keyword, but you'll use compile-time checking. But considering that you use object[], that's a small price:
dynamic results = obj.GetData();
object something = results[0][1];
I've not checked it with a compiler though.
(2) instead of Select(o => (type)o) there's a dedicated Cast<> function:
var tmp = items.Select(o => (object[])o).ToArray();
var tmp = items.Cast<object[]>().ToArray();
They are almost the same. I'd guess that Cast is a bit faster, but again, I've not checked that.
(3) Yes, reshaping in that way will affect the performance somewhat, depending mostly on the amount of items. The impact will be the larger the more elements you have. That's mostly related to .ToArray as it will enumerate all the items and it will make an additional array. Consider this:
var results = ((object[])obj.GetData()).Cast<object[]>();
The 'results' here are of type IEnumerable<object[]> and the difference is that it will be enumerated lazily, so the extra iteration over all elements is gone, the temporary extra array is gone, and also the overhead is minimal - similar to manual casting of every element, which you'd do anyways.. But - you lose the ability to index over the topmost array. You can loop/foreach over it, but you cannot index/[123] it.
EDIT:
The James's wrapper way is probably the best in terms of overall performance. I like it the most for readability, but that's personal opinion. Others may like LINQ more. But, I like it. I'd suggest James' wrapper.
You could use extension method:
static int getValue(this object[] arr, int col, int row)
{
return (int) ((object[])arr[row])[col];
}
And retrieve by
int requestedValue = arr.getValue(col, row);
No idea for arr[int x][int y] syntax.
EDIT
Thanks James for your observation
You can use a nullable int so you don't get an exception when casting.
So, the method will become:
static int? getIntValue(this object[] arr, int col, int row)
{
try
{
int? returnVal = ((object[])arr[row])[col] as int;
return returnVal;
}
catch(){ return null; }
}
And can be retrieved by
int? requestedValue = arr.getIntValue(col, row);
This way you get a nullable object and all encountered exceptions force return null
You can use LINQ Cast operator instead of Select...
object[][] arr = result.Cast<object[]>().ToArray()
This is a little less verbose, but should be nearly identical performance wise. Another way is to do it manually:
object[][] arr = new object[result.Length][];
for (int i = 0; i < arr.Length; ++i)
arr[i] = (object[])result[i];

Create an enumeration of one

If I want an empty enumeration, I can call Enumerable.Empty<T>(). But what if I want to convert a scalar type to an enumeration?
Normally I'd write new List<string> {myString} to pass myString to a function that accepts IEnumerable<string>. Is there a more LINQ-y way?
You can use Repeat:
var justOne = Enumerable.Repeat(value, 1);
Or just an array of course:
var singleElementArray = new[] { value };
The array version is mutable of course, whereas Enumerable.Repeat isn't.
Perhaps the shortest form is
var sequence = new[] { value };
There is, but it's less efficient than using a List or Array:
// an enumeration containing only the number 13.
var oneIntEnumeration = Enumerable.Repeat(13, 1);
You can also write your own extension method:
public static class Extensions
{
public static IEnumerable<T> AsEnumerable<T>(this T item)
{
yield return item;
}
}
Now I haven't done that, and now that I know about Enumerable.Repeat, I probably never will (learn something new every day). But I have done this:
public static IEnumerable<T> MakeEnumerable<T>(params T[] items)
{
return items;
}
And this, of course, works if you call it with a single argument. But maybe there's something like this in the framework already, that I haven't discovered yet.

How to iterate over two arrays at once?

I have two arrays built while parsing a text file. The first contains the column names, the second contains the values from the current row. I need to iterate over both lists at once to build a map. Right now I have the following:
var currentValues = currentRow.Split(separatorChar);
var valueEnumerator = currentValues.GetEnumerator();
foreach (String column in columnList)
{
valueEnumerator.MoveNext();
valueMap.Add(column, (String)valueEnumerator.Current);
}
This works just fine, but it doesn't quite satisfy my sense of elegance, and it gets really hairy if the number of arrays is larger than two (as I have to do occasionally). Does anyone have another, terser idiom?
You've got a non-obvious pseudo-bug in your initial code - IEnumerator<T> extends IDisposable so you should dispose it. This can be very important with iterator blocks! Not a problem for arrays, but would be with other IEnumerable<T> implementations.
I'd do it like this:
public static IEnumerable<TResult> PairUp<TFirst,TSecond,TResult>
(this IEnumerable<TFirst> source, IEnumerable<TSecond> secondSequence,
Func<TFirst,TSecond,TResult> projection)
{
using (IEnumerator<TSecond> secondIter = secondSequence.GetEnumerator())
{
foreach (TFirst first in source)
{
if (!secondIter.MoveNext())
{
throw new ArgumentException
("First sequence longer than second");
}
yield return projection(first, secondIter.Current);
}
if (secondIter.MoveNext())
{
throw new ArgumentException
("Second sequence longer than first");
}
}
}
Then you can reuse this whenever you have the need:
foreach (var pair in columnList.PairUp(currentRow.Split(separatorChar),
(column, value) => new { column, value })
{
// Do something
}
Alternatively you could create a generic Pair type, and get rid of the projection parameter in the PairUp method.
EDIT:
With the Pair type, the calling code would look like this:
foreach (var pair in columnList.PairUp(currentRow.Split(separatorChar))
{
// column = pair.First, value = pair.Second
}
That looks about as simple as you can get. Yes, you need to put the utility method somewhere, as reusable code. Hardly a problem in my view. Now for multiple arrays...
If the arrays are of different types, we have a problem. You can't express an arbitrary number of type parameters in a generic method/type declaration - you could write versions of PairUp for as many type parameters as you wanted, just like there are Action and Func delegates for up to 4 delegate parameters - but you can't make it arbitrary.
If the values will all be of the same type, however - and if you're happy to stick to arrays - it's easy. (Non-arrays is okay too, but you can't do the length checking ahead of time.) You could do this:
public static IEnumerable<T[]> Zip<T>(params T[][] sources)
{
// (Insert error checking code here for null or empty sources parameter)
int length = sources[0].Length;
if (!sources.All(array => array.Length == length))
{
throw new ArgumentException("Arrays must all be of the same length");
}
for (int i=0; i < length; i++)
{
// Could do this bit with LINQ if you wanted
T[] result = new T[sources.Length];
for (int j=0; j < result.Length; j++)
{
result[j] = sources[j][i];
}
yield return result;
}
}
Then the calling code would be:
foreach (var array in Zip(columns, row, whatevers))
{
// column = array[0]
// value = array[1]
// whatever = array[2]
}
This involves a certain amount of copying, of course - you're creating an array each time. You could change that by introducing another type like this:
public struct Snapshot<T>
{
readonly T[][] sources;
readonly int index;
public Snapshot(T[][] sources, int index)
{
this.sources = sources;
this.index = index;
}
public T this[int element]
{
return sources[element][index];
}
}
This would probably be regarded as overkill by most though ;)
I could keep coming up with all kinds of ideas, to be honest... but the basics are:
With a little bit of reusable work, you can make the calling code nicer
For arbitrary combinations of types you'll have to do each number of parameters (2, 3, 4...) separately due to the way generics works
If you're happy to use the same type for each part, you can do better
if there are the same number of column names as there are elements in each row, could you not use a for loop?
var currentValues = currentRow.Split(separatorChar);
for(var i=0;i<columnList.Length;i++){
// use i to index both (or all) arrays and build your map
}
In a functional language you would usually find a "zip" function which will hopefully be part of a C#4.0 . Bart de Smet provides a funny implementation of zip based on existing LINQ functions:
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> func)
{
return first.Select((x, i) => new { X = x, I = i })
.Join(second.Select((x, i) => new { X = x, I = i }),
o => o.I,
i => i.I,
(o, i) => func(o.X, i.X));
}
Then you can do:
int[] s1 = new [] { 1, 2, 3 };
int[] s2 = new[] { 4, 5, 6 };
var result = s1.Zip(s2, (i1, i2) => new {Value1 = i1, Value2 = i2});
If you're really using arrays, the best way is probably just to use the conventional for loop with indices. Not as nice, granted, but as far as I know .NET doesn't offer a better way of doing this.
You could also encapsulate your code into a method called zip – this is a common higher-order list function. However, C# lacking a suitable Tuple type, this is quite crufty. You'd end up returning an IEnumerable<KeyValuePair<T1, T2>> which isn't very nice.
By the way, are you really using IEnumerable instead of IEnumerable<T> or why do you cast the Current value?
Use IEnumerator for both would be nice
var currentValues = currentRow.Split(separatorChar);
using (IEnumerator<string> valueEnum = currentValues.GetEnumerator(), columnEnum = columnList.GetEnumerator()) {
while (valueEnum.MoveNext() && columnEnum.MoveNext())
valueMap.Add(columnEnum.Current, valueEnum.Current);
}
Or create an extension methods
public static IEnumerable<TResult> Zip<T1, T2, TResult>(this IEnumerable<T1> source, IEnumerable<T2> other, Func<T1, T2, TResult> selector) {
using (IEnumerator<T1> sourceEnum = source.GetEnumerator()) {
using (IEnumerator<T2> otherEnum = other.GetEnumerator()) {
while (sourceEnum.MoveNext() && columnEnum.MoveNext())
yield return selector(sourceEnum.Current, otherEnum.Current);
}
}
}
Usage
var currentValues = currentRow.Split(separatorChar);
foreach (var valueColumnPair in currentValues.Zip(columnList, (a, b) => new { Value = a, Column = b }) {
valueMap.Add(valueColumnPair.Column, valueColumnPair.Value);
}
Instead of creating two seperate arrays you could make a two-dimensional array, or a dictionary (which would be better). But really, if it works I wouldn't try to change it.

Categories