Populating a list of integers in .NET - c#

I need a list of integers from 1 to x where x is set by the user. I could build it with a for loop eg assuming x is an integer set previously:
List<int> iList = new List<int>();
for (int i = 1; i <= x; i++)
{
iList.Add(i);
}
This seems dumb, surely there's a more elegant way to do this, something like the PHP range method

If you're using .Net 3.5, Enumerable.Range is what you need.
Generates a sequence of integral
numbers within a specified range.

LINQ to the rescue:
// Adding value to existing list
var list = new List<int>();
list.AddRange(Enumerable.Range(1, x));
// Creating new list
var list = Enumerable.Range(1, x).ToList();
See Generation Operators on LINQ 101

I'm one of many who has blogged about a ruby-esque To extension method that you can write if you're using C#3.0:
public static class IntegerExtensions
{
public static IEnumerable<int> To(this int first, int last)
{
for (int i = first; i <= last; i++)
{
yield return i;
}
}
}
Then you can create your list of integers like this
List<int> = first.To(last).ToList();
or
List<int> = 1.To(x).ToList();

Here is a short method that returns a List of integers.
public static List<int> MakeSequence(int startingValue, int sequenceLength)
{
return Enumerable.Range(startingValue, sequenceLength).ToList<int>();
}

Related

Null Values Exception handling in Linq C# [duplicate]

I only found a way to do it the opposite way round: create a comma separated string from an int list or array, but not on how to convert input like string str = "1,2,3,4,5"; to an array or list of ints.
Here is my implementation (inspired by this post by Eric Lippert):
public static IEnumerable<int> StringToIntList(string str)
{
if (String.IsNullOrEmpty(str))
{
yield break;
}
var chunks = str.Split(',').AsEnumerable();
using (var rator = chunks.GetEnumerator())
{
while (rator.MoveNext())
{
int i = 0;
if (Int32.TryParse(rator.Current, out i))
{
yield return i;
}
else
{
continue;
}
}
}
}
Do you think this is a good approach or is there a more easy, maybe even built in way?
EDIT: Sorry for any confusion, but the method needs to handle invalid input like "1,2,,,3" or "###, 5," etc. by skipping it.
You should use a foreach loop, like this:
public static IEnumerable<int> StringToIntList(string str) {
if (String.IsNullOrEmpty(str))
yield break;
foreach(var s in str.Split(',')) {
int num;
if (int.TryParse(s, out num))
yield return num;
}
}
Note that like your original post, this will ignore numbers that couldn't be parsed.
If you want to throw an exception if a number couldn't be parsed, you can do it much more simply using LINQ:
return (str ?? "").Split(',').Select<string, int>(int.Parse);
If you don't want to have the current error handling behaviour, it's really easy:
return text.Split(',').Select(x => int.Parse(x));
Otherwise, I'd use an extra helper method (as seen this morning!):
public static int? TryParseInt32(string text)
{
int value;
return int.TryParse(text, out value) ? value : (int?) null;
}
and:
return text.Split(',').Select<string, int?>(TryParseInt32)
.Where(x => x.HasValue)
.Select(x => x.Value);
or if you don't want to use the method group conversion:
return text.Split(',').Select(t => t.TryParseInt32(t)
.Where(x => x.HasValue)
.Select(x => x.Value);
or in query expression form:
return from t in text.Split(',')
select TryParseInt32(t) into x
where x.HasValue
select x.Value;
Without using a lambda function and for valid inputs only, I think it's clearer to do this:
Array.ConvertAll<string, int>(value.Split(','), Convert.ToInt32);
--EDIT-- It looks like I took his question heading too literally - he was asking for an array of ints rather than a List --EDIT ENDS--
Yet another helper method...
private static int[] StringToIntArray(string myNumbers)
{
List<int> myIntegers = new List<int>();
Array.ForEach(myNumbers.Split(",".ToCharArray()), s =>
{
int currentInt;
if (Int32.TryParse(s, out currentInt))
myIntegers.Add(currentInt);
});
return myIntegers.ToArray();
}
quick test code for it, too...
static void Main(string[] args)
{
string myNumbers = "1,2,3,4,5";
int[] myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 15.
myNumbers = "1,2,3,4,5,6,bad";
myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 21
Console.ReadLine();
}
Let us assume that you will be reading the string from the console. Import System.Linq and try this one:
int[] input = Console.ReadLine()
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
This has been asked before. .Net has a built-in ConvertAll function for converting between an array of one type to an array of another type. You can combine this with Split to separate the string to an array of strings
Example function:
static int[] ToIntArray(this string value, char separator)
{
return Array.ConvertAll(value.Split(separator), s=>int.Parse(s));
}
Taken from here
This is for longs, but you can modify it easily to work with ints.
private static long[] ConvertStringArrayToLongArray(string str)
{
return str.Split(",".ToCharArray()).Select(x => long.Parse(x.ToString())).ToArray();
}
I don't see why taking out the enumerator explicitly offers you any advantage over using a foreach. There's also no need to call AsEnumerable on chunks.
import java.util.*;
import java.io.*;
public class problem
{
public static void main(String args[])enter code here
{
String line;
String[] lineVector;
int n,m,i,j;
Scanner sc = new Scanner(System.in);
line = sc.nextLine();
lineVector = line.split(",");
//enter the size of the array
n=Integer.parseInt(lineVector[0]);
m=Integer.parseInt(lineVector[1]);
int arr[][]= new int[n][m];
//enter the array here
System.out.println("Enter the array:");
for(i=0;i<n;i++)
{
line = sc.nextLine();
lineVector = line.split(",");
for(j=0;j<m;j++)
{
arr[i][j] = Integer.parseInt(lineVector[j]);
}
}
sc.close();
}
}
On the first line enter the size of the array separated by a comma. Then enter the values in the array separated by a comma.The result is stored in the array arr.
e.g
input:
2,3
1,2,3
2,4,6
will store values as
arr = {{1,2,3},{2,4,6}};

Can you loop through an enum in C#?

for (int i = (int)MY_ENUM.First; i <= (int)MY_ENUM.Last; i++)
{
//do work
}
Is there a more elegant way to do this?
You should be able to utilize the following:
foreach (MY_ENUM enumValue in Enum.GetValues(typeof(MY_ENUM)))
{
// Do work.
}
Enums are kind of like integers, but you can't rely on their values to always be sequential or ascending. You can assign integer values to enum values that would break your simple for loop:
public class Program
{
enum MyEnum
{
First = 10,
Middle,
Last = 1
}
public static void Main(string[] args)
{
for (int i = (int)MyEnum.First; i <= (int)MyEnum.Last; i++)
{
Console.WriteLine(i); // will never happen
}
Console.ReadLine();
}
}
As others have said, Enum.GetValues is the way to go instead.
Take a look at Enum.GetValues:
foreach (var value in Enum.GetValues(typeof(MY_ENUM))) { ... }
The public static Array GetValues(Type enumType) method returns an array with the values of the anEnum enumeration. Since arrays implements the IEnumerable interface, it is possible to enumerate them.
For example :
EnumName[] values = (EnumName[])Enum.GetValues(typeof(EnumName));
foreach (EnumName n in values)
Console.WriteLine(n);
You can see more detailed explaination at MSDN.

Fill List<int> with default values? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Auto-Initializing C# Lists
I have a list of integers that has a certain capacity that I would like to automatically fill when declared.
List<int> x = new List<int>(10);
Is there an easier way to fill this list with 10 ints that have the default value for an int rather than looping through and adding the items?
Well, you can ask LINQ to do the looping for you:
List<int> x = Enumerable.Repeat(value, count).ToList();
It's unclear whether by "default value" you mean 0 or a custom default value.
You can make this slightly more efficient (in execution time; it's worse in memory) by creating an array:
List<int> x = new List<int>(new int[count]);
That will do a block copy from the array into the list, which will probably be more efficient than the looping required by ToList.
int defaultValue = 0;
return Enumerable.Repeat(defaultValue, 10).ToList();
if you have a fixed length list and you want all the elements to have the default value, then maybe you should just use an array:
int[] x = new int[10];
Alternatively this may be a good place for a custom extension method:
public static void Fill<T>(this ICollection<T> lst, int num)
{
Fill(lst, default(T), num);
}
public static void Fill<T>(this ICollection<T> lst, T val, int num)
{
lst.Clear();
for(int i = 0; i < num; i++)
lst.Add(val);
}
and then you can even add a special overload for the List class to fill up to the capacity:
public static void Fill<T>(this List<T> lst, T val)
{
Fill(lst, val, lst.Capacity);
}
public static void Fill<T>(this List<T> lst)
{
Fill(lst, default(T), lst.Capacity);
}
Then you can just say:
List<int> x = new List(10).Fill();
Yes
int[] arr = new int[10];
List<int> list = new List<int>(arr);
var count = 10;
var list = new List<int>(new int[count]);
ADD
Here is generic method to get the list with default values:
public static List<T> GetListFilledWithDefaulValues<T>(int count)
{
if (count < 0)
throw new ArgumentException("Count of elements cannot be less than zero", "count");
return new List<T>(new T[count]);
}

Need help in terminating deferred execution

The following snippet prints 1 through 10 on the console, but does not terminate until variable 'i' reaches int.MaxValue. TIA for pointing out what I am missing.
class Program
{
public static IEnumerable<int> GetList()
{
int i = 0;
while (i < int.MaxValue)
{
i++;
yield return i;
}
}
static void Main(string[] args)
{
var q = from i in GetList() // keeps calling until i reaches int.MaxValue
where i <= 10
select i;
foreach (int i in q)
Console.WriteLine(i);
}
}
You could try:
var q = GetList ().TakeWhile ((i)=> i <=10);
The query that you defined in Main doesn't know anything about the ordering of your GetList method, and it must check every value of that list with the predicate i <= 10. If you want to stop processing sooner, you will you can use the Take extension method or use the TakeWhile extension method:
foreach (int i in GetList().Take(10))
Console.WriteLine(i);
foreach (int i in GetList().TakeWhile(x => x <= 10))
Console.WriteLine(i);
Your iterators limits are 0 through Int32.MaxValue, so it will process that whole range. Iterators are only smart enough to not pre-iterate the results of the range of data you design it to iterate. However they are not smart enough to know when the code that uses them no longer needs more unless you tell it so (i.e. you break out of a foreach loop.) The only way to allow the iterator to limit itself is to pass in the upper bound to the GetList function:
public static IEnumerable<int> GetList(int upperBound)
{
int i = 0;
while (i < upperBound)
{
i++;
yield return i;
}
}
You could also explicitly tell the iterator that you only wish to iterate the first 10 results:
var numbers = GetList().Take(10);
Consider using the LINQ extension method .Take() with your argument instead of having it in your where clause. More on Take.
var q = from i in GetList().Take(10)
select i;

Order an Array like another Array in C#

What is the best algorithm to take array like below:
A {0,1,2,3}
I expected to order it like array below:
B {3,1,0,2}
Any ideas?
So if you have two arrays and they hold the same data just in different order then just do this:
A = B
I suspect that is not your situation so I think we need more info.
What you need to do is determine the ordering of B and then apply that ordering to A. One way to accomplish this is to undo the ordering of B and keep track of what happens along the way. Then you can do the reverse to A.
Here's some sketchy C# (sorry, I haven't actually run this)...
Take a copy of B:
List<int> B2 = new List<int>(B);
Now sort it, using a sort function that records the swaps:
List<KeyValuePair<int,int>> swaps = new List<KeyValuePair<int,int>>();
B2.Sort( delegate( int x, int y ) {
if( x<y ) return -1;
if( x==y ) return 0;
// x and y must be transposed, so assume they will be:
swaps.Add( new KeyValuePair<int,int>(x,y) );
return 1;
});
Now apply the swaps, in reverse order, to A:
swaps.Reverse();
foreach( KeyValuePair<int,int> x in swaps )
{
int t = A[x.key];
A[x.key] = A[x.value];
A[x.value] = t;
}
Depending how the built-in sort algorithm works, you might need to roll your own. Something nondestructive like a merge sort should give you the correct results.
Here's my implementation of the comparer (uses LINQ, but can be easily adapted to older .net versions). You can use it for any sorting algorithms such as Array.Sort, Enumerable.OrderBy, List.Sort, etc.
var data = new[] { 1, 2, 3, 4, 5 };
var customOrder = new[] { 2, 1 };
Array.Sort(data, new CustomOrderComparer<int>(customOrder));
foreach (var v in data)
Console.Write("{0},", v);
The result is 2,1,3,4,5, - any items not listed in the customOrder are placed at the end in the default for the given type (unless a fallback comparator is given)
public class CustomOrderComparer<TValue> : IComparer<TValue>
{
private readonly IComparer<TValue> _fallbackComparer;
private const int UseDictionaryWhenBigger = 64; // todo - adjust
private readonly IList<TValue> _customOrder;
private readonly Dictionary<TValue, uint> _customOrderDict;
public CustomOrderComparer(IList<TValue> customOrder, IComparer<TValue> fallbackComparer = null)
{
if (customOrder == null) throw new ArgumentNullException("customOrder");
_fallbackComparer = fallbackComparer ?? Comparer<TValue>.Default;
if (UseDictionaryWhenBigger < customOrder.Count)
{
_customOrderDict = new Dictionary<TValue, uint>(customOrder.Count);
for (int i = 0; i < customOrder.Count; i++)
_customOrderDict.Add(customOrder[i], (uint) i);
}
else
_customOrder = customOrder;
}
#region IComparer<TValue> Members
public int Compare(TValue x, TValue y)
{
uint indX, indY;
if (_customOrderDict != null)
{
if (!_customOrderDict.TryGetValue(x, out indX)) indX = uint.MaxValue;
if (!_customOrderDict.TryGetValue(y, out indY)) indY = uint.MaxValue;
}
else
{
// (uint)-1 == uint.MaxValue
indX = (uint) _customOrder.IndexOf(x);
indY = (uint) _customOrder.IndexOf(y);
}
if (indX == uint.MaxValue && indY == uint.MaxValue)
return _fallbackComparer.Compare(x, y);
return indX.CompareTo(indY);
}
#endregion
}
In the example you gave (an array of numbers), there would be no point in re-ordering A, since you could just use B.
So, presumably these are arrays of objects which you want ordered by one of their properties.
Then, you will need a way to look up items in A based on the property in question (like a hashtable). Then you can iterate B (which is in the desired sequence), and operate on the corresponding element in A.
Both array's contain the same values (or nearly so) but I need to force them to be in the same order. For example, in array A the value "3045" is in index position 4 and in array B it is in index position 1. I want to reorder B so that the index positions of like values are the same as A.
If they are nearly the same then here is some pseudo code:
Make an ArrayList
Copy the contents of the smaller array to the arraylist
for each item I in the larger array
FInd I in the ArrayList
Append I to a new array
Remove I from the arraylist
Could the issue be resolved using a Dictionary so the elements have a relationship that isn't predicated on sort order at all?

Categories