0
\$\begingroup\$

If I had an array of integers like

+--------------------------------------------+
| 1| 0| 1| 2| 0| 1| 0| 1| 0|-1| 0| 2| 0|-2| 0| > VALUES
+--------------------------------------------+
| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14| > INDEX
+--------------------------------------------+

I am looking for 0 which occurs 7 times in the array above.

But I need to find indexes of 0s in the array like so:

  1. I can find 0's that occur only after a slot with a Abs(value)> 1 (rising of falling)
  2. I can find 0's that occur only after a slot with a value> 1 (rising)
  3. I can find 0's that occur only after slot with a negative Abs(value)

    1 (falling)

So, looking at array above my logic should show indexes

  • 1, 4, 12, 14 - 1st and REST (rising or falling)
  • 1, 4, 12 - 1st and RISING
  • 1, 14 - 1st and FALLING

The indexes above are valid since the previous value was (Abs(previous)> 1). On the other hand, 0's at index 6, 8, and 10 are of no interest since the previous array value was either 1 or -1 (so Abs(previous) <= 1)

My code below works but I feel there could be a simpler more elegant solution to this

public static void Main(string[] args)
{
 int[] array = new int[15] { 1, 0, 1, 2, 0, 1, 0, 1, 0, -1, 0, 2, 0, -2, 0 };
 bool found1 = true;
 for (int i = 0; i < array.Length; i++)
 {
 if (array[i] == 0)
 {
 if (found1)
 {
 Console.WriteLine(i); //print 1st index of 0
 found1 = false;
 }
 else
 {
 if (Math.Abs(array[i - 1] - array[i]) > 1)
 {
 Console.WriteLine("All: " + i); // print every other that fits
 //1, 4, 12, 14
 }
 }
 }
 }
 found1 = true;
 for (int i = 0; i < array.Length; i++)
 {
 if (array[i] == 0)
 {
 if (found1)
 {
 Console.WriteLine(i); //print 1st index of 0
 found1 = false;
 }
 else
 {
 if (Math.Abs(array[i - 1] - array[i]) > 1
 && (array[i - 1] - array[i]) > 1)
 {
 Console.WriteLine("Up: " + i); // print rising
 //1, 4, 12
 }
 }
 }
 }
 found1 = true;
 for (int i = 0; i < array.Length; i++)
 {
 if (array[i] == 0)
 {
 if (found1)
 {
 Console.WriteLine(i); //print 1st index of 0
 found1 = false;
 }
 else
 {
 if (Math.Abs(array[i - 1] - array[i]) > 1
 && (array[i - 1] - array[i]) < 1)
 {
 Console.WriteLine("Down: " + i); // print falling
 //1, 14
 }
 }
 }
 }
 Console.ReadLine();
}
t3chb0t
44.6k9 gold badges84 silver badges190 bronze badges
asked Mar 4, 2018 at 3:10
\$\endgroup\$
7
  • 2
    \$\begingroup\$ Are you looking to reduce the amount of code, or improve performance? For example, you could use int firstIndex = Array.IndexOf(array, 0); to give the first index of 0. And you could reduce this down to just one loop (storing the results in 3 separate List<int> variables based on if/else conditions) \$\endgroup\$ Commented Mar 4, 2018 at 3:19
  • \$\begingroup\$ @StephenMuecke Thank you. I am not concerned here with array or loops. The array data is really coming from an event listener having new and previous value passed into handler. I am just wondering if there is a more elegant way to detect the change based on these 2 values passed into handler. \$\endgroup\$ Commented Mar 4, 2018 at 3:35
  • 1
    \$\begingroup\$ Not sure what you are concerned with then, and I do not know how you intend to use the results, but I might re-write that code as per this Gist \$\endgroup\$ Commented Mar 4, 2018 at 3:49
  • \$\begingroup\$ @StephenMuecke Much appreciated Stephen. Can you post answer so I can accept it. Thanks again \$\endgroup\$ Commented Mar 4, 2018 at 4:05
  • \$\begingroup\$ Sure, but I'm still not sure how you wanted to use the results or what you mean by detect the change based on these 2 values (what 2 values are you referring to) and if that would change the code \$\endgroup\$ Commented Mar 4, 2018 at 4:08

2 Answers 2

4
\$\begingroup\$

You are unnecessarily looping through the array 3 times (only one loop is required). Its not clear how you will be using the results, but assuming you need to store them, then the code can be simplified to

int[] array = new int[15] { 1, 0, 1, 2, 0, 1, 0, 1, 0, -1, 0, 2, 0, -2, 0 };
// Define 3 lists from the results
List<int> all = new List<int>();
List<int> up = new List<int>();
List<int> down = new List<int>();
// Get the index of the first zero value and add to the lists
int first = Array.IndexOf(array, 0);
all.Add(first);
up.Add(first);
down.Add(first);
// Loop the remaining items in the array and add to the appropriate lists
for (int i = first + 1; i < array.Length; i++)
{
 int current = array[i];
 int previous = array[i - 1];
 if (current != 0)
 {
 continue;
 }
 if (Math.Abs(previous - current) > 1)
 {
 all.Add(i);
 if (previous - current > 1)
 {
 up.Add(i);
 }
 else if (previous - current < 1)
 {
 down.Add(i);
 }
 }
}

The result is

all contains [1, 4, 12, 14], up contains [1, 4, 12] and down contains [1, 14]

answered Mar 4, 2018 at 4:22
\$\endgroup\$
1
\$\begingroup\$

A lot of extra code in my opinion
You don't need 3 loops
You don't test the first
If the value is zero there is not purpose to subtracting it

public static void Zero()
{
 int[] array = new int[15] { 1, 0, 1, 2, 0, 1, 0, 1, 0, -1, 0, 2, 0, -2, 0 };
 List<int> all = new List<int>();
 List<int> up = new List<int>();
 List<int> down = new List<int>();
 int previous = array[0];
 int current;
 for (int i = 1; i < array.Length; i++)
 {
 current = array[i];
 if (current == 0)
 {
 if (previous < -1)
 {
 all.Add(i);
 down.Add(i);
 }
 else if (previous > 1)
 {
 all.Add(i);
 up.Add(i);
 }
 }
 previous = current;
 }
 Debug.WriteLine("done");
}
answered Mar 4, 2018 at 9:52
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.