using where to get every other number starting with the last - c#

I have an array of numbers {3, 6, 1, 5, 5, 6} I am trying to get every other number starting with the last number.
The correct result would then be 6, 5, 6 the only way I have been able to get this to work is to use Reverse.
int[] digitList = {3, 6, 1, 5, 5,6};
var rev = digitList.Reverse().Where((x, i) => i % 2 == 0).Reverse().ToList();
// Correct results in 6,5,6
var l = digitList.Where((x, i) => i % 2 == 0).ToList();
// Incorrect results in 3,1,5
Is there a way of doing this without the Reverse? How can i tell Where() to start at the other end?

If the count is odd, then every other number from the start, if it's even then take every other number from the second one (or skip the first), that removes the need for a reverse operation. For example:
int[] digitList = { 3, 6, 1, 5, 5, 6 };
//Skip 1 if count is odd, otherwise skip zero
var skipCount = digitList.Count() % 2 == 0 ? 1 : 0;
var l = digitList
.Skip(skipCount)
.Where((x, i) => i % 2 == 0)
.ToList();

You have to check for odd/even length arrays; to amend your current code you
should change the == 0 condition:
int[] digitList = { 3, 6, 1, 5, 5, 6, 7, 8 };
var rev = digitList
.Where((x, i) => i % 2 != digitList.Length % 2) // not "== 0"
.ToList();

Related

Sum of selected values in an int Array in c#

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();

Lambda expressions: index of an element in the array

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);
var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);
var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);
These are C# code taken from http://msdn.microsoft.com/en-us/library/bb397687.aspx
I understand the first two lambda expressions just fine by considering n as an element of the array "numbers".
However the third lambda expression is really confusing with "index". Is (n,index) one of the lambda parameters well established for arrays? Is this a convention?
When TakeWhile iterates over the collection:
n is the value of the element
index is the index of the element
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
// As TakeWhile iterates over the array:
// "n" is the value of the element
// "index" is the index of the element
var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);
foreach(var n in firstSmallNumbers)
Console.WriteLine(n);
Output:
5 4
Run this at: https://dotnetfiddle.net/4NXRkg

How to split array in two arrays?

I have one array and want split it in to two:
Now: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
New_1: [0, 2, 4, 6, 8]
New_2: [1, 3, 5, 7, 9]
So take the one element and skip the next element.
Look easy but how can i do it with C#?
Thanks a lot
You can use linq, Enumerable.Where and get the array with elements that have even and odd indexes.
var New_1 = arr.Where((c,i) => i % 2 == 0).ToArray();
var New_2 = arr.Where((c,i) => i % 2 != 0).ToArray();
You can get the index of element of collection and apply condition to check if index is even or odd and get the arrays according.
Enumerable.Where Method (IEnumerable, Func) filters a sequence of values based on a predicate.
Each element's index is used in the logic of the predicate function.
The first argument of predicate represents the element to test. The
second argument represents the zero-based index of the element within
source, msdn
How about something like
int[] arr = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int[] arr1 = arr.Where((x, i) => i % 2 == 0).ToArray();
int[] arr2 = arr.Where((x, i) => i % 2 == 1).ToArray();
int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i = 0;
List<int[]> twoArr = arr.GroupBy(x => i++ % 2).Select(g => g.ToArray()).ToList();

Array.Sort in with nontrivial comparison function

Consider the following code from C# 5.0 in a Nutshell, p. 289:
int[] numbers = { 1, 2, 3, 4, 5 };
Array.Sort (numbers, (x, y) => x % 2 == y % 2 ? 0 : x % 2 == 1 ? -1 : 1);
which gives result {3, 5, 1, 2, 4}.
I tried this on a paper and got {1, 3, 5, 2, 4}.
Why computer sorting gave 3 > 5 > 1 ?
Most likely the topic is about the fact that Sort does not guarantee the order of elements which are equal. Unlike stable sort algorithms that preserve original order of equal elements "unstable sort" may swap them. Normally when you do sorting by hand you do "stable sort" version.
Array.Sort:
This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved. In contrast, a stable sort preserves the order of elements that are equal.
The sort function used in sample makes 1 == 3, 1 == 5 so unstable sort is allowed to order this numbers in any way as long as they are in correct order compared to other ones: 1,3,5 (stable - same order as in source) or any sequence 3,1,5 (unstable sort).
I.e. OrderBy implements "stable sort" and you can see results in following sample using the same compare function:
void Main()
{
int[] numbers = { 1, 2, 3, 4, 5 };
var result = numbers.OrderBy(x=> x, new MyComparer()));
// 1, 3, 5, 2, 4
}
public class MyComparer : IComparer<int>
{
public int Compare( int x, int y)
{
return x % 2 == y % 2 ? 0 : x % 2 == 1 ? -1 : 1;
}
}
Although Array.Sort specifies
If the partition size is fewer than 16 elements, it uses an insertion sort algorithm.
it does not specifiy how it does this insertion sort or which flavor of insertion sort it uses. As already mentioned, it additionally specifies
This implementation performs an unstable sort
and as a result, the only thing Array.Sort promises about the order of the elements after returning is that they are sorted. This is true for {3, 5, 1, 2, 4}.
Consider that the algorithm used by Array.Sort would even be allowed to do something like this (Pseudocode):
if sequence = {1, 2, 3, 4, 5} then
sequence := {3, 5, 1, 2, 4}
end if
Sort(sequence);
This, of course, would be implementation defined behavior, and it could change in another version of the .NET framework.
Modifying your code to be
Array.Sort(numbers, (x, y) =>
{
Console.WriteLine(x + ", " + y);
return x % 2 == y % 2 ? 0 : x % 2 == 1 ? -1 : 1;
});
will give you the comparisons that are done by Array.Sort:
1, 3
1, 5
3, 5
1, 3
3, 5
2, 3
3, 4
3, 3
5, 3
5, 3
5, 5
5, 3
2, 4
2, 1
4, 2
1, 4
4, 4
4, 2
1, 2
1, 2
1, 1
1, 2
1, 1
And this, very likely, is not how you would do an insertion sort on paper.
The point is: Array.Sort promises to sort your sequence, but it does not promise how to do this.
That code is equivalent to:
static void Main(string[] args)
{
int[] numbers = { 1, 2, 3, 4, 5 };
Array.Sort(numbers, OnComparison);
}
private static int OnComparison(int x, int y)
{
if (x%2 == y%2) return 0;
if (x%2 == 1) return 1;
return -1;
}
I get:
{3, 5, 1, 2, 4}
The sorting operation goes like this:
0) {1,2,3,4,5}
1) {1,2,3,4,5}
2) {1,2,3,4,5}
3) {1,2,3,4,5}
4) {1,2,3,4,5}
5) {5,2,3,4,1}
6) {5,2,3,4,1}
7) {5,2,3,4,1}
8) {5,3,2,4,1}
9) {5,3,2,4,1}
10) {5,3,2,4,1}
11) {5,3,2,4,1}
12) {3,5,2,4,1}
13) {3,5,2,4,1}
14) {3,5,1,4,2}
15) {3,5,1,4,2}
16) {3,5,1,4,2}
17) {3,5,1,4,2}
18) {3,5,1,2,4}
19) {3,5,1,2,4}
20) {3,5,1,2,4}
21) {3,5,1,2,4}
22) {3,5,1,2,4}
23) Final: {3,5,1,2,4}
So in conclusion, it seems the "why" is because the 0 problem as everybody says, but I am not completelly sure yet.
Here you are not sort equal remainders how you got in order
try this:
Array.Sort(numbers, (x, y) => x % 2 == y % 2 ? x < y ? 1 : -1 : x % 2 == 1 ? -1 : 1);
here are how i understand it ,
base on the code, you can change it as :
static void Main(string[] args)
{
int[] numbers = { 1, 2, 3, 4, 5 };
Array.Sort(numbers, OnComparison);
}
private static int OnComparison(int x, int y)
{
if (x%2 == y%2) return 0;
if (x%2 == 1) return -1;
return 1;
}
so arrary.sort, is sorting on condition (OnComparison,which by the return value), not compare with int[] numbers.
so 3 & 5 & 1, both return as -1
and as the definition of array.sort :
This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved
that why , you got {3, 5, 1, 2, 4}

Linq query that reduces a subset of duplicates to a single value within a larger set?

Is there a linq command that will filter out duplicates that appear in a sequence?
Example with '4':
Original { 1 2 3 4 4 4 5 6 7 4 4 4 8 9 4 4 4 }
Filtered { 1 2 3 4 5 6 7 4 8 9 4 }
Thanks.
Not really. I'd write this:
public static IEnumerable<T> RemoveDuplicates(this IEnumerable<T> sequence)
{
bool init = false;
T current = default(T);
foreach (var x in sequence)
{
if (!init || !object.Equals(current, x))
yield return x;
current = x;
init = true;
}
}
Yes there is! One-line code and one loop of the array.
int[] source = new int[] { 1, 2, 3, 4, 4, 4, 5, 6, 7, 4, 4, 4, 8, 9, 4, 4, 4 };
var result = source.Where((item, index) => index + 1 == source.Length
|| item != source[index + 1]);
And according to #Hogan's advice, it can be better:
var result = source.Where((item, index) => index == 0
|| item != source[index - 1]);
More readable now i think. It means "choose the first element, and those which isn't equal to the previous one".
Similar to svick's answer, except with side effects to avoid the cons and reverse:
int[] source = new int[] { 1, 2, 3, 4, 4, 4, 5, 6, 7, 4, 4, 4, 8, 9, 4, 4, 4 };
List<int> result = new List<int> { source.First() };
source.Aggregate((acc, c) =>
{
if (acc != c)
result.Add(c);
return c;
});
Edit: No longer needs the source.First() as per mquander's concern:
int[] source = new int[] { 1, 2, 3, 4, 4, 4, 5, 6, 7, 4, 4, 4, 8, 9, 4, 4, 4 };
List<int> result = new List<int>();
result.Add(
source.Aggregate((acc, c) =>
{
if (acc != c)
result.Add(acc);
return c;
})
);
I think I still like Danny's solution the most.
You can use Aggregate() (although I'm not sure whether it's better than the non-LINQ solution):
var ints = new[] { 1, 2, 3, 4, 4, 4, 5, 6, 7, 4, 4, 4, 8, 9, 4, 4, 4 };
var result = ints.Aggregate(
Enumerable.Empty<int>(),
(list, i) =>
list.Any() && list.First() == i
? list
: new[] { i }.Concat(list)).Reverse();
I think it's O(n), but I'm not completely sure.
If you're using .NET 4 then you can do this using the built-in Zip method, although I'd probably prefer to use a custom extension method like the one shown in mquander's answer.
// replace "new int[1]" below with "new T[1]" depending on the type of element
var filtered = original.Zip(new int[1].Concat(original),
(l, r) => new { L = l, R = r })
.Where((x, i) => (i == 0) || !object.Equals(x.L, x.R))
.Select(x => x.L);

Categories

Resources