Can you cast a List<int> to List<string> somehow?
I know I could loop through and .ToString() the thing, but a cast would be awesome.
I'm in C# 2.0 (so no LINQ).
.NET 2.0 has the ConvertAll method where you can pass in a converter function:
List<int> l1 = new List<int>(new int[] { 1, 2, 3 } );
List<string> l2 = l1.ConvertAll<string>(delegate(int i) { return i.ToString(); });
Updated for 2010
List<int> l1 = new List<int>(new int[] { 1,2,3 } );
List<string> l2 = l1.ConvertAll<string>(x => x.ToString());
Is C# 2.0 able to do List<T>.Convert? If so, I think your best guess would be to use that with a delegate:
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Convert(delegate (int i) { return i.ToString(); });
Something along those lines.
Glenn's answer is probably the correct code ;-)
You can use:
List<int> items = new List<int>(new int[] { 1,2,3 } );
List<string> s = (from i in items select i.ToString()).ToList();
You wouldn't be able to directly cast it as no explicit or implicit cast exists from int to string, it would have to be a method involving .ToString() such as:-
foreach (int i in intList) stringList.Add(i.ToString());
Edit - or as others have pointed out rather brilliantly, use intList.ConvertAll(delegate(int i) { return i.ToString(); });, however clearly you still have to use .ToString() and it's a conversion rather than a cast.
result = listOfInt.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToList()
replace the parameters result and listOfInt to your parameters
Converting from int List to string List can be done in two adittional ways besides the usual ToString(). Choose the one that pleases you more.
var stringlist = intlist.Select(x=>""+x).ToList();
Or also:
var stringlist = intlist.Select(x=>$"{x}").ToList();
And finally the traditional:
var stringlist = intlist.Select(x=>x.ToString()).ToList();
You have to build a new list. The underlying bit representations of List<int> and List<string> are completely incompatible -- on a 64-bit platform, for instance, the individual members aren't even the same size.
It is theoretically possible to treat a List<string> as a List<object> -- this gets you into the exciting worlds of covariance and contravariance, and is not currently supported by C# or VB.NET.
Related
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();
}
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.
I have a List<int> myInts and want to multiply all with 10. I want to use linq (not foreach loop).I tryed this but nothing happend:
List<int> myInts = new List<int>() { 1, 2, 3 };
myInts .ForEach(act => act=act*10);
Of what do I have to take care in the .ForEach(...) part? And yes, I want to use ForEach if it is somehow possible.
Probably its simple, but I cant see it, I apoligize. Thank you all!
This creates a new instance of List.
myInts = myInts.Select(p=>p*10).ToList();
Another and simpler solution:
list = list.ConvertAll(i => i * 10);
"Nothing happens" because reassigning to the local variable (act) has no effect in the caller (ForEach) - C# is Call By Value (except for ref/out parameters).
To modify the list in place, simply use a standard for-each over the indices (which I find readable and upfront of the side-effect intent):
var myInts = new List<int>() { 1, 2, 3 };
for (var i = 0; i < myInts.Count; i++) {
myInts[i] = myInts[i] * 10;
}
To perform the operation and create a new list/sequence (which can be re-assigned to the same variable), see IEnumerable.Select which is a map transformation.
From MSDN documentation:
Modifying the underlying collection in the body of the Action<T> delegate
is not supported and causes undefined behavior.
So, you need to project your exisistin List into a new one, or you need to use a for loop if you must modify the List "in place"
Regards
What is happening is that you are getting a value copy of the int to your the lambda, which so you won't be able to change the 'external' int.
How about projecting a new list?
List<int> myInts = new List<int>() { 1, 2, 3 };
myInts = myInts.Select(act => act*10).ToList();
To use a .Select or .ConvertAll are good solutions.
But my intention was to let "ForEach" return an alterd list.
I found out, over msdn documentation, that this isn´t possible because ForEach is a void type and has no returntype.
This kind of action works if I would have objects in my List instead of ints. Then I would be able to use the "void" Method to change the properties of my objects.
Do you mean like this ?
List<int> _tempList = new List<int>();
myInts.ToList().ForEach(x => _tempList.Add(x * 10));
try this:
Enumerable.Range(0, myInts.Count).ToList().ForEach(i => myInts[i] = myInts[i] * 10);
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();
I'd like to populate an arraylist by specifying a list of values just like I would an integer array, but am unsure of how to do so without repeated calls to the "add" method.
For example, I want to assign { 1, 2, 3, "string1", "string2" } to an arraylist. I know for other arrays you can make the assignment like:
int[] IntArray = {1,2,3};
Is there a similar way to do this for an arraylist? I tried the addrange method but the curly brace method doesn't implement the ICollection interface.
Depending on the version of C# you are using, you have different options.
C# 3.0 has collection initializers, detail at Scott Gu's Blog
Here is an example of your problem.
ArrayList list = new ArrayList {1,2,3};
And if you are initializing a collection object, most have constructors that take similar components to AddRange, although again as you mentioned this may not be an option.
Array list has ctor which accepts ICollection, which is implemented by the Array class.
object[] myArray = new object[] {1,2,3,"string1","string2"};
ArrayList myArrayList = new ArrayList(myArray);
(kind of answering my own question but...)
The closest thing I've found to what I want is to make use of the ArrayList.Adapter method:
object[] values = { 1, 2, 3, "string1", "string2" };
ArrayList AL = new ArrayList();
AL = ArrayList.Adapter(values);
//or during intialization
ArrayList AL2 = ArrayList.Adapter(values);
This is sufficient for what I need, but I was hoping it could be done in one line without creating the temporary array as someone else had suggested.
Your comments imply you chose ArrayList because it was the first component you found.
Assuming you are simply looking for a list of integers, this is probably the best way of doing that.
List<int> list = new List<int>{1,2,3};
And if you are using C# 2.0 (Which has generics, but not collection initializers).
List<int> list = new List<int>(new int[] {1, 2, 3});
Although the int[] format may not be correct in older versions, you may have to specify the number of items in the array.
I assume you're not using C# 3.0, which has collection initializers. If you're not bothered about the overhead of creating a temp array, you could do it like this in 1.1/2.0:
ArrayList list = new ArrayList(new object[] { 1, 2, 3, "string1", "string2"});