If Start=0 and Count=10 then how to get the alternate values using Enumerable.Range()
the out put should be like { 0, 2, 4, 6, 8 }
and if Start=1 and Count=10 then { 1, 3, 5, 7, 9 }
The continuous value can be get like
var a = Enumerable.Range(0,10).ToList();
but how to get the alternate values?
Halving the number of items that Range should generate (its second parameter) and then doubling the resulting values will give both the correct number of items and ensure an increment of 2.
Enumerable.Range(0,5).Select(x => x * 2)
Enumerable.Range(0, 10).Where(i => i % 2 == 0); // { 0, 2, 4, 6, 8 }
Enumerable.Range(0, 10).Where(i => i % 2 != 0); // { 1, 3, 5, 7, 9 }
The count parameter in your code looks like an end point of the loop.
public static MyExt
{
public static IEnumerable<int> Range(int start, int end, Func<int, int> step)
{
//check parameters
while (start <= end)
{
yield return start;
start = step(start);
}
}
}
Usage: MyExt.Range(1, 10, x => x + 2) returns numbers between 1 to 10 with step 2
MyExt.Range(2, 1000, x => x * 2) returns numbers between 2 to 1000 with multiply 2 each time.
What you are after here does not exist in the BCL as far as I'm aware of, so you have to create your own static class like this to achieve the required functionality:
public static class MyEnumerable {
public static IEnumerable<int> AlternateRange(int start, int count) {
for (int i = start; i < start + count; i += 2) {
yield return i;
}
}
}
Then you can use it like this wherever you want to:
foreach (int i in MyEnumerable.AlternateRange(0, 10)) {
//your logic here
}
You can then also perform LINQ queries using this since it returns IEnumerable
So if you want you can also write the above like this if you want to exclude the number 6
foreach (int i in MyEnumerable.AlternateRange(0, 10).Where( j => j != 6)) {
//your logic here
}
I hope this is what you are after.
You can't have this as an extension method on the Enumerable class directly since that is a static class, and extension methods work on an object of a class, and not the class itself. That's why you have to create a new static class to hold this method if you want to mimic the Enumerable class.
This can be done more simply using Linq and by specifying the minimum, length, and step values:
Enumerable.Range(min, length).Where(i => (i - min) % step == 0);
Usage with 0 through 10 at a step size of 2:
var result = Enumerable.Range(0, 10).Where(i => (i - 10) % 2 == 0);
Output:
0, 2, 4, 6, 8
Usage with 1 through 10 at a step size of 2:
var result = Enumerable.Range(1, 10).Where(i => (i - 10) % 2 == 0);
Output:
1, 3, 5, 7, 9
You could go further and make a simple function to output it using a minimum, maximum, and step value:
public static IEnumerable<int> RangedEnumeration(int min, int max, int step)
{
return Enumerable.Range(min, max - min + 1).Where(i => (i - min) % step == 0);
}
The reason to set the range length to max - min + 1 is to ensure the max value is inclusive. If the max should be exclusive, remove the + 1.
Usage:
var Result = RangedEnumeration(0, 10, 2); // 0, 2, 4, 6, 8, 10
var Result = RangedEnumeration(1, 10, 2); // 1, 3, 5, 7, 9
var Result = RangedEnumeration(1000, 1500, 150); // 1000, 1150, 1300, 1450
Related
I'm learning how to program using c#. I'm really new to this.
My question is I'm trying to create an array that shows 10 numbers. I want my code to check which numbers below 10 are divisible for 3 or 5 and sum the total.
I've tried to use the .Sum() function but says int doesn't contain a definition for Sum. I've put using System.Linq on my program.
Does anyone have an idea how to make this sum happens?
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int sum = 1 + 2;
foreach (int n in numbers)
{
if (n % 3 == 0 || n % 5 == 0)
{
int total = n.Sum();
Console.WriteLine(total);
}
else
{
Console.WriteLine("not divisible");
}
}`
So your problem is that you are trying to call .Sum() on a variable n which is of type int (you define it here: foreach (int n in numbers), and that is not a method.
Using LINQ you could do something like:
var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var total = numbers.Where(n => n % 3 == 0 || n % 5 == 0).Sum();
If I understand it correct and using your code this is what you want.
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int sum = 1 + 2;
int total=0;
foreach (int n in numbers)
{
if (n % 3 == 0 || n % 5 == 0)
{
int total += n;
}
else
{
Console.WriteLine("not divisible");
}
}
Console.WriteLine(total);
I moved the printing out to after the foreach so you get one result when it is done
Everybody forgot that array should contain 10 numbers but some numbers values maybe greater than 10. Only number values below 10 should be checked. So a right answer should be
var numbers = new int[] { 1, 9, 5, 6, 8, 10,4, 15, 25, 3};
var total = numbers.Where( n => (n<10) && ( n % 3 == 0 || n % 5 == 0)).Sum();
I want to return elements between two variable indexes in a list.
For example, given this list -
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
I want to loop through the list using to variables for index values. Let’s call the index values X and Y.
So if X equals an index value of 0 and Y equals a value of 5, I need to loop through the index 0-5 and return all of the element values. X and Y could later become index values of 5 through 8 for example.
How would I accomplish this?
You can use Enumerable.Skip and Enumerable.Take
var res = list.Skip(noOfElementToSkip).Take(noOfElementsToTake);
To using variable as indexes
var res = list.Skip(x).Take(y-x+1);
Note You need to pass the start element index to Skip and for taking number of elements you need to pass number of element you want in Take parameter minus the start element number, plus one list is zero-based index.
you can use List.GetRange
var result = list.GetRange(X, Y-X+1);
or a simple for loop
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int i = X; i <= Y; i++)
{
Console.WriteLine(list[i]);
}
or reinventing the wheel the way you want
public static class Extensions
{
public static IEnumerable<T> GetRange<T>(this IList<T> list, int startIndex, int endIndex)
{
for (int i = startIndex; i <= endIndex; i++)
{
yield return list[i];
}
}
}
foreach(var item in list.GetRange(0, 5))
{
Console.WriteLine(item);
}
int x = 0, y = 5;
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (; x < y; x++)
{
Console.WriteLine(list[x]);
}
This would work if X is always smaller than Y.
If you don't know which is bigger add this before the loop:
if (x > y)
{
x = x ^ y;
y = y ^ x;
x = x ^ y;
}
Another alternative:
int X = 0, Y = 5;
Enumerable.Range(X, Y - X + 1)
.Select(index => list[index]);
It should do the trick -
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int startindex = 1;
int endIndex = 7;
var subList = list.Skip(startindex).Take(endIndex - startindex-1).ToList();
I have a list of integer lists, like that:
A -> 10 10 1 1 1
B -> 10 9 9 7 6
...
I would like to sort them based on how many 10s they have, then on how many 9s, 8s, 7s, and so on untile the 1s
So in the example above A should be better than B because even if it has less total points, it has two 10s instead of only 1.
Code should be generic because I don't know how many numbers will be available for each case (sometimes 10, sometimes 5, or even only 3).
I developed something like that:
lists.OrderByDescending(a => a.Where(b => b == 10).Count()).
ThenByDescending(a => a.Where(b => b == 9).Count()).
and so on, but this is not generic...
I hope the question is clear... thank you very much!
You can create query which orders lists by count of 10s, then compose query by adding additional orderings for numbers from 9 to 1:
var query = lists.OrderByDescending(l => l.Count(x => x == 10));
for (int i = 9; i >= 1; i--)
query = query.ThenByDescending(l => l.Count(x => x == i));
For these sample lists:
var lists = new[] {
new[] { 10, 9, 9, 8, 7 },
new[] { 10, 9, 9, 7, 6 },
new[] { 10, 10, 1, 1, 1 }
};
Result will be:
[10, 10, 1, 1, 1]
[10, 9, 9, 8, 7]
[10, 9, 9, 7, 6]
It's simple, but not very efficient. If you need better performance, then consider creating custom comparer. Here is sample with comparer which uses zipped ordered sequences to check if all items in sequences are same, or get first item which is different:
public class CustomComparer : Comparer<IList<int>>
{
public override int Compare(IList<int> x, IList<int> y)
{
var comparisons = x.Zip(y, (a,b) => a.CompareTo(b));
foreach(var comparison in comparisons)
{
if (comparison != 0)
return comparison;
}
return x.Count.CompareTo(y.Count);
}
}
NOTE: If items in lists are not ordered, then you should sort them before zipping:
var comparisons =
x.OrderByDescending(i => i)
.Zip(y.OrderByDescending(i => i), (a,b) => a.CompareTo(b));
It works very simple. Consider two lists:
[10, 9, 9, 8, 7, 5]
[10, 9, 9, 7, 6]
It will create pairs of items in corresponding positions:
{10,10}, {9,9}, {9,9}, {8,7}, {7,6}
Then items in each pair will be compared one by one, until first mismatch will be found:
0, 0, 0, 1 (four comparisons only)
That means first list has more 8s than second one. Usage:
var query = lists.OrderByDescending(i => i, new CustomComparer());
Result is same.
The following comparer
public class Comparer : IComparer<IEnumerable<int>>
{
public int Compare(IEnumerable<int> a, IEnumerable<int> b)
{
var aOrdered = a.OrderByDescending(i => i).Concat(new[] { int.MinValue });
var bOrdered = b.OrderByDescending(i => i).Concat(new[] { int.MinValue });
return a.Zip(b, (i, j) => i.CompareTo(j)).FirstOrDefault(c => c != 0);
}
}
lets you order you lists of lists like so
var result = lists.OrderByDescending(i => i, new Comparer());
without iterating through each list ten times counting individual elements.
This compares the lists and returns conventional comparison result - 1, 0, or -1 is returned depending on whether one value is greater than, equal to, or less than the other.
static int CompareLists(List<int> a, List<int> b)
{
var grpA = a.GroupBy(p => p).ToDictionary(k=>k.Key,v=>v.Count());
var grpB = b.GroupBy(p => p).ToDictionary(k=>k.Key,v=>v.Count());
for (int i = 10; i >= 0; i--)
{
int countA = grpA.ContainsKey(i) ? grpA[i] : 0;
int countB = grpB.ContainsKey(i) ? grpB[i] : 0;
int comparison = countA.CompareTo(countB);
if (comparison != 0)
return comparison;
}
return 0;
}
First we convert the lists into dictionary of number->amount of occurences.
Then we iterate through numbers from 10 to 0 and compare the number of occurences. If the result is 0, then we go to another number.
If you have List<List<int>> to sort, just use list.Sort(CompareLists) as in:
List<int> d = new List<int> { 10, 6, 6 };
List<int> b = new List<int> { 10, 9, 9 };
List<int> a = new List<int> { 10, 10, 1, 1, 1 };
List<int> c = new List<int> { 10, 7, 7 };
List<int> e = new List<int> { 9, 3, 7 };
List<int> f = new List<int> { 9, 9, 7 };
List<List<int>> list = new List<List<int>>() { a, b, c, d, e, f };
list.Sort(CompareLists);
Let's say I have a list of numbers like
1 2 3 4 5 6 7 8 9 10
Now I want to delete 50% of the list so i would have now a list like
1 3 5 7 9
I don't want to remove the first 50% , so not this
6 7 8 9 10
I want to regularly delete from the list.
I'm trying to implement this in C# or JAVA.
I know that sometime is not possible to remove that percent exactly but something close will be ok.
My procent is always an integer, so is from 0 to 100 .
I'm trying to do this with an N percent for a list, how should I start?
You can use Linq:
List<int> source = new List<int>() {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Take every other item from the list
List<int> result = source
.Where((item, index) => index % 2 == 0)
.ToList();
General case should be elaborated a little bit:
int percent = 50;
List<int> result = source
.Where((item, index) =>
(index == 0) ||
(index * percent / 100) > ((index - 1) * percent / 100))
.ToList();
int halfNumOfList = myList.Count / 2;
int itemsRemoved = 0;
for (int i = 0; i < myList.Count; i++)
{
if (itemsRemoved < halfNumOfList)
{
if (i % 2 != 0)
{
myList.Remove(myList[i]);
itemsRemoved++;
}
}
}
I have an array of items that prints to pdf in the following order.
Lets say for eg:
lines = {1, 2, 3,
4, 5, 6,
7, 8, 9,
10}
is the content of my array.
However I want to change the order of the items in the array to
{1, 4, 7,
2, 5, 8,
3, 6, 9,
10}
Then I pass this array to my print engine. Basically if there are more than 3 items in the array, my new code should reorder it.
Could somebody help me figuring out the logic for that.
Thanks
Order the lines by the modulus of the line index with the number of rows.
public static ICollection<T> Sort<T>(ICollection<T> lines, int columns)
{
var rows = lines.Count/columns;
if (rows == 0)
{
return lines;
}
return lines.Select((line, i) => new {line, i})
.OrderBy(item => item.i < columns*rows ? item.i%rows : rows)
.Select(item => item.line)
.ToList();
}
Edit: Alternatively you can use an iterator method and the list's indexer instead of LINQ:
public static IEnumerable<T> Sort<T>(IList<T> lines, int columns)
{
var rows = lines.Count/columns;
for (var i = 0; i < lines.Count; i++)
{
var index = rows > 0 && i < columns*rows
? (i%columns)*rows + i/columns
: i;
yield return lines[index];
}
}
Assuming "for linear array assuming every 9 elements form 3x3 matrix transpose each subsequence, keep remainder as-is":
// assuming T[] items;
var toTranspose = (items.Count() / 9) * 9;
var remap = new int[]{1, 4, 7, 2, 5, 8, 3, 6, 9 };
var result = Enumerable.Range(0, toTranspose)
.Select(pos => items[(pos / 9) * 9 + (remap[pos % 9] - 1)])
.Concat(items.Skip(toTranspose)
.ToArray();
Summary of code:
get number of items that need to be moved (which is number of groups of 9 items int numberOfGroup = Count()/9;, multiplied by group size)
have custom transformation in remap array (note that indexes copied as-is from sample and actually off-by-one hence -1 in computing index)
for each element index under toTranspose get source element from corresponding group and apply transformation with remap.
finally Concat the remainder.
Notes:
one can easily provide custom transformation or inline transposition if needed.
can't apply transformation to the last partial group as elements will have to go to non-existent positions.