mr_blond
mr_blond

Reputation: 1730

How do I define that value crosses 0 in C#?

There is list of int variable

data = List<int>

It contains few ints above the 0, few int's under 0 and so on. Data looks like:

-2962
-5787
-1671
-5667
-498
-4463
1399
3608
2173

I need to find the first item, when this function crosses the 0 from + to - (or from - to +) to get only first items above 0 or first items under 0 (depends on the sign of first item if it + or -).

So my code is:

var itemSign = 0;

foreach (var item in data)
{
    if (itemSign == Sign(item))
    {
        result.Add(item);
        Console.WriteLine(item);
    }
    itemSign = Sign(item);
}

But output is:

-2962
-5787
-1671
-5667
-498
-4463
1399
3608
2173

It seems like it doesn't work at all because I need to get these ints in these case:

-2962
-5787
-1671
-5667
-498
-4463

How do I define that value crosses 0 in C#?

Upvotes: 2

Views: 161

Answers (4)

John Alexiou
John Alexiou

Reputation: 29254

There are two versions I can think of. Both use the List<int>.FindIndex() method.

class Program
{
    static void Main(string[] args)
    {
        var list = new List<int>() {
            -2962   ,
            -5787   ,
            -1671   ,
            -5667   ,
            -498    ,
            -4463   ,
            1399    ,
            3608    ,
            2173    ,
        };

        int index = list.FindIndex((x) => x>0)-1;
        // index = 5

        index=list.Zip(list.Skip(1), (x, y) => Math.Sign(x*y)).ToList().FindIndex((s) => s==-1);
        // index = 5
    }
}

The first one returns the index of the first non-negative number.

The second one multiplies consecutive numbers and if their product has a negative sign it means the numbers just changed sign.

Upvotes: 1

Johnny
Johnny

Reputation: 9519

Usint System.Linq (just for fun)

var input = new List<int> { -2962, -5787, -1671, -5667, -498, -4463, 1399, 3608, 2173 };

var cross = input
    .Zip(input.Skip(1), (a, b) => new []{a,b})
    .TakeWhile(t => (t.First() ^ t.Last()) >> 31 == 0)
    .SelectMany(_ => _)
    .Distinct();

Console.WriteLine(string.Join(",", cross)); //-2962,-5787,-1671,-5667,-498,-4463

If you want just the last element in the row, or first, then Aggregate could work:

var cross = input.Aggregate((a,b) => (a ^ b) >> 31 == 0 ? a : b); //1399
var cross = input.Aggregate((a,b) => (a ^ b) >> 31 == 0 ? b : a); //-4463

Upvotes: 0

Mehrdad Dowlatabadi
Mehrdad Dowlatabadi

Reputation: 1335

You can use break as soon as sign change appears :

var itemSign = Sign(data.FirstOrDefault());
var result = new List<int>();
foreach (var item in data)
{
    if (itemSign == Sign(item))
    {
        result.Add(item);
        Console.WriteLine(item);
    }
    else
        break;
}

Upvotes: 3

Technivorous
Technivorous

Reputation: 1712

for each element in list, if >0 add to positive list, if <0 add to negative list. this is simple if else stuff....

Upvotes: -3

Related Questions