列表中的值在减少和增加时分离

时间:2013-10-03 12:11:17

标签: c# arrays algorithm list multidimensional-array

这就是我想做的事。

我在列表中有大量的数字,但它有一个增加或减少的序列。

如, 100 200 300 400 500 600 500 400 300 200 100 500 700 800 900

让我们说这些值存储在列表或数组中。我怎么能将这些分成多个数组或由序列组成的列表。

例如,清单1:100 200 300 400 500 600 清单2:500 400 300 200 100 清单3:500 700 800 900

这就是我所做的。我被卡住了。

for (int i = 0; i < p.Count - 1; i++)
{
    double v = p.ElementAt(i);
    if (initialP > v)
    {
        if (low == 1)
        {
            sep.Add(sep_index);
            low = 0;
        }
        else
        {

        }
        high = 1;
    }

    if (initialP < v)
    {
        if (high == 1)
        {
            sep.Add(sep_index);
            high = 0;
        }
        low = 1;
    }
    initialP = v;
    sep_index++;

    if (i == p.Count - 2)
    {
        sep.Add(sep_index);
    }
}

5 个答案:

答案 0 :(得分:2)

正如评论中所建议的那样,你应该使用一个列表列表,当循环使用一个新列表时,如果在排序方向上有一个开关:

编辑:已修复以考虑相同的数字和严格的比较。

    public static List<List<int>> GetLists(int[] nums, bool strict) { 
        List<List<int>> lists = new List<List<int>>();
        List<int> list = new List<int>();
        lists.Add(list);
        list.AddRange(nums.Take(1));
        if (nums.Length <= 1) {
            return lists;
        }
        if (strict && nums[0] == nums[1]) {
            list = new List<int>();
            lists.Add(list);
            list.Add(nums[1]);
        }
        else
            list.Add(nums[1]);


        if (nums.Length == 2)
        {
            return lists;
        }

        int direction = Math.Sign(nums[2] - nums[1]);
        for (int i = 2; i < nums.Length; i++) {
            int d = Math.Sign(nums[i] - nums[i - 1]);
            if ((d == direction && (d != 0 || !strict))
                    || (d != 0 && strict)
                    || (Math.Abs(d + direction) == 1 && !strict))
            {
                list.Add(nums[i]);
                if (d != 0 && direction == 0) direction = d;
            }
            else
            {
                direction = d;
                list = new List<int>();
                list.Add(nums[i]);
                lists.Add(list);
            }
        }
        return lists;
    }

    static void Main(string[] args)
    {
        int[] nums = new int[] { 2, 2, 2, 1, 1, 3, 3, 4, 4 };
        var lists = GetLists(nums, false);
        foreach (var list in lists) {
            foreach (var item in list)
            {
                Console.Write(item + " ");
            }
            Console.WriteLine();
        }
        /*
         * Prints:
         * 2 2 2 1 1
         * 3 3 4 4
         * */
    }

答案 1 :(得分:0)

派生或旋转。如果是积极的 - 一个方向。否则 - 另一个。 使用旋转,它将显示方向(向上或向下):( n + 1 / n)。当旋转发生变化时,则将元素存储在列表中。

答案 2 :(得分:0)

我会做这样的事情:

private static List<int[]> SplitOnDirection(int[] input)
{
    List<int[]> output = new List<int[]>();
    List<int> currentList = new List<int>();

    bool? isRaising = null;
    int? previousNumber = null;

    foreach (int number in input)
    {
        // do we have a previous value?
        if (previousNumber.HasValue)
        {
            // only if the number is different, then we have to check the direction.
            if (number != previousNumber.Value)
            {
                bool isHigherNumber = (number > previousNumber.Value);

                // do we already know if we start with raise/lowering
                if (isRaising.HasValue)
                {
                    // if we have a higher number and we're not raising, change direction.
                    if (isHigherNumber != isRaising.Value)
                    {
                        // We changed direction..
                        output.Add(currentList.ToArray());
                        currentList = new List<int>();
                    }
                }

                isRaising = isHigherNumber;
            }
        }

        previousNumber = number;
        currentList.Add(number);
    }
    // if we didn't changed direction, we should 'flush' these.
    if (currentList.Count > 0)
        output.Add(currentList.ToArray());

    return output;
}

int[] input = new int[] { 100, 200, 300, 400, 500, 600, 500, 400, 300, 200, 100, 500, 700, 800, 900 };

List<int[]> output = SplitOnDirection(input);

答案 3 :(得分:0)

可能的解决方案:

    public static IList<IList<int>> UpDownSeparator(IEnumerable<int> value) {
      if (Object.ReferenceEquals(null, value))
        throw new ArgumentNullException("value");

      List<IList<int>> result = new List<IList<int>>();

      List<int> current = new List<int>();
      result.Add(current);

      // +1 - asceding, -1 - descending, 0 - to be determined later
      int direction = 0;

      foreach(int item in value) {
        if (direction == 0) {
          if (current.Count > 0) {
            if (item > current[current.Count - 1])
              direction = 1;
            else if (item < current[current.Count - 1])
              direction = -1;
          }

          current.Add(item);
        }
        else if (direction < 0) {
          if (item > current[current.Count - 1]) {
            direction = 1;
            current = new List<int>() { item };
            result.Add(current);
          }
          else
            current.Add(item);
        }
        else {
          if (item < current[current.Count - 1]) {
            direction = -1;
            current = new List<int>() { item };
            result.Add(current);
          }
          else
            current.Add(item);
        }
      }

      return result;
    }

....

  List<int> list = new List<int>() { 100, 200, 300, 400, 500, 600, 500, 400, 300, 200, 100, 500, 700, 800, 900};

  // [[100, 200, 300, 400, 500, 600], [500, 400, 300, 200, 100], [500, 700, 800, 900]]
  IList<IList<int>> result = UpDownSeparator(list);

答案 4 :(得分:0)

大约20分钟,但我会在下面做这样的事情。使用Java,我确信可以使用其他语言语法轻松编写。

Input
1, 1, 1, -1, 2, 3, 4, 4, 4, 5, 6, 5, 4, 4, 3, 3, 6, 6, 2, 1, 5, 7, 8, 9
Output
1 1 1 -1 
2 3 4 4 4 5 6 
5 4 4 3 3 
6 6 
2 1 
5 7 8 9 

代码

public static void main(String[] args) {
    int[] input = new int[]{1, 1, 1, -1, 2, 3, 4, 4, 4, 5, 6, 5, 4, 4, 3, 3, 6, 6, 2, 1, 5, 7, 8, 9};
    List<List<Integer>> lists = split(input);
    for (List<Integer> list : lists) {
        for (Integer integer : list) {
            System.out.print(integer+" ");
        }
        System.out.println("");
    }
}

public static List<List<Integer>> split(int[] input) {
    List<List<Integer>> listOfList = new ArrayList<List<Integer>>();
    if(input.length >= 1) {
        List<Integer> list = newList(listOfList, input[0]);
        Order lastO = null;
        int last = input[0];

        for (int i = 1; i < input.length; i++) {
            Order currentO = Order.getOrder(input[i], last);
            boolean samePattern = Order.sameDirection(currentO, lastO);

            if(lastO == null || samePattern) {
                list.add(input[i]);
            } else {
                list = newList(listOfList, input[i]);
                lastO = null;
            }

            if(currentO != Order.Equal){
                lastO = currentO;
            }
            last = input[i];
        }
    } 
    return listOfList;
}

private static List<Integer> newList(List<List<Integer>> listOfList, int element) {
    List<Integer> list = new ArrayList<Integer>();
    listOfList.add(list);
    list.add(element);
    return list;
}


private static enum Order {
    Less, High, Equal;

    public static Order getOrder(int first, int second) {
        return first > second ? High : first < second ? Less : Equal;  
    }

    public static boolean sameDirection(Order current, Order last) {
        if(last == Order.Less && (current == Order.Less  || current == Order.Equal)) {
            return true;
        } else if(last == Order.High && (current == Order.High  || current == Order.Equal)) {
            return true;
        }
        return false;
    }
}