Best way to do a split and convert the result into ints - c#

I have a DB table that contains a comma separated list of ID's (ints) that are stored as nvarchar.
I have a get method to return these in one hit as a list. At the moment I think I'll have to do something like this:
List<int> ids = new List<int>();
string[] pageids = experssion.Split(separators)
foreach (string number in pageids)
{
ids.Add(Convert.ToInt32(number));
}
Can anyone think of a nicer way to do this ? Can I do it all on the split somehow ?

I'd to it like this:
var ids = expression.Split(separator).Select(s => int.Parse(s));
It uses the Linq extensions of .NET 3.0. As an alternative (saves one lambda), you could also do this which is arguably less readable:
var ids = expression.Split(separator).Select((Func<string, int>)int.Parse);

If you're not using C# 3.0, or aren't a fan of LINQ, you could do it the C# 2.0 way:
// This gives you an int[]
int[] pageids = Array.ConvertAll(expression.Split(separator), new Converter<string,int>(StringToInt));
// Add each id to the list
ids.AddRange(pageids);
public static int StringToInt(string s)
{
return int.Parse(s);
}
EDIT:
Or, even simpler as per Konrad's suggestion:
int[] pageids = Array.ConvertAll<string,int>(expression.Split(separator),int.Parse);
ids.AddRange(pageids);

With LINQ you can do this:
List<int> ids
= expression
.Split(separators)
.Select(number => Convert.ToInt32(number))
.ToList()

Related

Sort List<T> with an array

Basically I have a list containing all items. Then I have a string containing the IDs I want to grab out from the list, to do this I split the string into an Int array and later use this and LINQ to get the items I want from the list
Like this :
List<T> lstAllList = Model.getAllItems();
string stringIDs = "8,9,12,11,7";
int[] intArray = stringIDs.Split(',').Select(n => Convert.ToInt32(n)).ToArray();
List<T> lstLimitedList = (from r in lstAllList where intArray.Contains(r.id) select r).ToList();
Which works great.
But the issue here is that I want to have my list ordered in the same way as the string of IDs is, i.e 8,9,12,11,7 like in this example.
But the returned list from the LINQ sorts it by the id by default, so the returned list is 7,8,9,11,12.
Is there a way to prevent it from sorting it like this or is there a way to sort the new list with my int array?
Sure, just sort by the index of the ID in the array:
string stringIDs = "8,9,12,11,7";
int[] intArray = stringIDs.Split(',').Select(n => Convert.ToInt32(n)).ToArray();
var lstLimitedList = (
from r in lstAllList
where intArray.Contains(r.id)
orderby Array.IndexOf(intArray, r.id) // <--------
select r).ToList();
Simply getting the elements one at a time may be faster than trying to resort. (Anyone willing to calculate the O() costs?)
List<T> lstLimitedList = new List<T>();
foreach(int id in intArray)
{
lstLimitedList.Add(lstAllList.Where(item => item.id = id));
}
You could also use intArray.ForEach() if you're a LINQ maniac, but this is much easier to read. ;)
Try to rotate your query. Under word rotate I mean start with intArray and use join. Something like this:
List<T> lstLimitedList = (
from id in intArray
join item in lstAllList on id equals item.Id
select item).ToList();
Id use the intersect extension method with provided by LINQ!
int[] array ={ 8,9,12,11,7} // or your result from your split on string;
List<int> array2 = new List<int> { 8,9,12,11,7 } // your model.GetAllItems;
// Call Intersect extension method.
var intersect = array.Intersect(array2);
// Write intersection to screen.
foreach (int value in intersect)
{
Console.WriteLine(value); // Output: 8,9,12,11,7
}
Bit cleaner for me
Stop overusing LINQ guys. In this case linq is a total overkill. A much simpler and better performance-wise solution is the following:
string a = "8,9,12,11,7";
List<int> list = new List<int>();
string[] splitted = a.Split(',');
for (int i = 0; i < splitted.Length; i++)
{
list.Add(int.Parse(splitted[i]));
}
Which a single loop and without sorting etc.

C# Object List to String List

I have List<object> that seems above, I want to convert it to List<string>.
How can I convert it ?
I need List<string> that has 6 items (11:00,13:45,.... etc)
var mylist = myObjectList.ConvertAll(x => x.ToString());
Edit
var mylist = myObjectList.ConvertAll(x => Convert.ToString(x));
thanks Scott Chamberlain
To get first array of objects
var mylist = (myObjectList.First() as object[]).ToList()
.ConvertAll(x=>Convert.ToString(x));
To add rest to the list.
mylist.AddRange(mylist.GetRange(1,myObjectList.Count-2).ConvertAll(x=>Convert.ToString(x)));
var stringList = yourObjectList.OfType<string>().ToList();
Remember to add the namespace System.Linq;
The OfType is needed to convert the array to an array<T> which is necessary in order to use it with LINQ
Try this
List<string> stringlist = objectList.Cast<string>()
.ToList();
If you're not certain about those elements are strings you can use Select
List<string> stringlist = objectList.Select(x=> x.ToString())
.ToList();
To avoid NullReferenceException in case of null values try the following
List<string> stringlist = objectList.Where(x=> x != null)
.Select(x=> x.ToString())
.ToList();
Using LINQ this is fairly easy. If you are sure they are all strings you can simply do
int i = //Some code that sets i, like a for loop
var oldList = seanceInfo.theatre[i].seances;
List<string> newList = oldList.Cast<string>().ToList();
If you are not sure all of the objects are strings you need to perform some kind of conversion, however that is just as easy
List<string> newList = oldList.Select(o => Convert.ToString(o)).ToList();
From your comment: "seances is List<object>, and first index of seances is object[]. I need these items.", I think what you really want may be a SelectMany
List<string> info = seanceInfo.theatre.SelectMany(x => x.seances).Select(x => Convert.ToString(x)).ToList();
This will take each seance in each theater and combine it in to one master list.
You can simply cast it using LinQ.
myObjectList.Cast<string>();
Or filter all non-string
myObjectList.OfType<string>();
Casting like :
var list = (List<String>) listObjects.

how to filter with linq and `contains`

I try to filter my items according to unknown number of filters.
//item.statusId is nullable int
//statusIds is a string
{...
var statusIds = Convert.ToString(items["StatusId"]);//.Split(';');
results = mMaMDBEntities.MamConfigurations.Where(item =>
FilterByStatusId(statusIds, item.StatusId)).ToList();
}
return results;
}
private bool FilterByStatusId(string statusIds, int? statusId)
{
return statusIds.Contains(statusId.ToString());
}
But I get this error:
LINQ to Entities does not recognize the method 'Boolean FilterByStatusId(System.String, System.Nullable1[System.Int32])' method, and this method cannot be translated into a store expression.`
Any idea how to re-write it?
If statusIds is an array then you can do:
results = mMaMDBEntities.MamConfigurations
.Where(item => statusIds.Contain(item.StatusID)).ToList();
Some what similar to SQL Select * from table where ID in (1,2,3)
EDIT:
From your code it appears you have a string with semicolon separated values. You can try the following to get an array of int and later use that in your LINQ expression.
var str = Convert.ToString(items["StatusId"]);//.Split(';');
// string str = "1;2;3;4;5"; //similar to this.
int temp;
int[] statusIds = str.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
.Select(r => int.TryParse(r, out temp) ? temp : 0)
.ToArray();
then later you can use the int array in your expression like:
results = mMaMDBEntities.MamConfigurations
.Where(item => statusIds.Contain(item.StatusID)).ToList();
Why not insert the predicate statement directly into the where clause?
like this:
results = mMaMDBEntities.MamConfigurations.Where(item => statusIds.Contains(item.StatusId).ToList();
you might need to convert the string array resulting from the Split to a List or IEnumerable to make this work.
The exception is pretty self-explanatory, the method cannot be converted to a SQL statement in the form you wrote it, but if you write it like above, you should obtain the same result and it will work.

How to convert List<int> to string[]?

I need an easy way to convert a List<int> to a string array.
I have:
var the_list = new List<int>();
the_list.Add(1);
the_list.Add(2);
the_list.Add(3);
string[] the_array = new string[the_list.Count];
for(var i = 0 ; i < the_array.Count; ++i)
the_array[i] = the_list[i].ToString();
...which looks to be very ugly to me.
Is there an easier way?
Note: I'm looking for an easier way - not necessarily a faster way.
Use LINQ:
string[] the_array = the_list.Select(i => i.ToString()).ToArray();
I know you have a good answer, but you don't need LINQ or Select. You can do it with a ConvertAll and an anonymous method. Like this:
var list = new List<int>();
....
var array = list.ConvertAll( x => x.ToString() ).ToArray();
Similar idea, but I think this is not linq. in case that matters.
Sorry, I don't have .NET installed on this machine, so totally untested:
var theList = new List<int>() { 1, 2, 3 };
var theArray = theList.Select(e => e.ToString()).ToArray(); // Lambda Form
var theArray = (from e in theList select e.ToString()).ToArray(); // Query Form
List has a ToArray() method. It will save you typing but probably won't be more efficient.
Because your list only has a number, you can easily convert them to a string. Just create a loop and convert its members to the string.
string[] the_array = new string[the_list.Count];
int i=0;
foreach(var item in the_list)
{
the_array[i] = item.ToString();
i++;
}

C# Converting List<int> to List<double>

I have a List<int> and I want to convert it to a List<double>. Is there any way to do this other than just looping through the List<int> and adding to a new List<double> like so:
List<int> lstInt = new List<int>(new int[] {1,2,3});
List<double> lstDouble = new List<double>(lstInt.Count);//Either Count or Length, I don't remember
for (int i = 0; i < lstInt.Count; i++)
{
lstDouble.Add(Convert.ToDouble(lstInt[0]));
}
Is there a fancy way to do this? I'm using C# 4.0, so the answer may take advantage of the new language features.
You can use Select as suggested by others, but you can also use ConvertAll:
List<double> doubleList = intList.ConvertAll(x => (double)x);
This has two advantages:
It doesn't require LINQ, so if you're using .NET 2.0 and don't want to use LINQBridge, you can still use it.
It's more efficient: the ToList method doesn't know the size of the result of Select, so it may need to reallocate buffers as it goes. ConvertAll knows the source and destination size, so it can do it all in one go. It can also do so without the abstraction of iterators.
The disadvantages:
It only works with List<T> and arrays. If you get a plain IEnumerable<T> you'll have to use Select and ToList.
If you're using LINQ heavily in your project, it may be more consistent to keep using it here as well.
You can use LINQ methods:
List<double> doubles = integers.Select<int, double>(i => i).ToList();
or:
List<double> doubles = integers.Select(i => (double)i).ToList();
Also, the list class has a ForEach method:
List<double> doubles = new List<double>(integers.Count);
integers.ForEach(i => doubles.Add(i));
You could do this using the Select extension method:
List<double> doubleList = intList.Select(x => (double)x).ToList();
You can use ConvertAll method inside of .Net Framework 2.0 here is an example
List<int> lstInt = new List<int>(new int[] { 1, 2, 3 });
List<double> lstDouble = lstInt.ConvertAll<double>(delegate(int p)
{
return (double)p;
});
You can use a method group:
lstDouble = lstInt.Select(Convert.ToDouble)
You can use Select or ConvertAll. Keep in mind that ConvertAll is available in .Net 2.0 too

Categories

Resources