当重复多次时,数组从前一个元素中扣除1

时间:2014-11-21 18:17:27

标签: ruby arrays

我有以下数组:

输入:

array = [211, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200]

输出:

array = [211, 200, 199, 198, 197, 196 ... ]

我已尝试each_with_index但无法获得所需的结果。

4 个答案:

答案 0 :(得分:2)

我不明白用nil做什么,所以我没有解决这个问题。根据要求,arrarrayarray.sort.reverse。我想这是你想要的吗? (见我对这个问题的评论。)

def change_em(arr)
  dup_indices = arr.each_index
                   .group_by { |i| arr[i] }
                   .values
                   .flat_map { |a| a.drop(1) }
  puts "dup_indices = #{dup_indices}"
  last = 0 # anything '-' responds to
  arr.each_index.map { |i| last = dup_indices.include?(i) ? last-1 : arr[i] }
end

我已经包含puts只是为了澄清我在这里做的事情。

change_em [10, 8, 5, 5, 7]
  #=> dup_indices = [3]
  #=> [10, 8, 5, 4, 7]
change_em [10, 8, 7, 5, 5]
  #=> dup_indices = [4]
  #=> [10, 8, 7, 5, 4]
change_em [10, 9, 9, 8, 8, 8]
  #=> dup_indices = [2, 4, 5]
  #=> [10, 9, 8, 8, 7, 6]
change_em [211, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 196]
  #=> dup_indices = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 
  #=> [211, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 196]

注意声明

last = dup_indices.include?(i) ? last-1 : arr[i]

正在执行double-duty:它会更新last的值并返回索引i的映射值。另请注意,dup_indices不能包含0

答案 1 :(得分:0)

写道这是一种更具功能性的风格。

def f(arr, dup_element = nil, dup_count = 0)
  return generate_dup_array(dup_element, dup_count) if arr.empty?
  if arr.head != arr.tail.head # Not duplicates
    if dup_count == 0 # No duplicates to insert
      [arr.head] + f(arr.tail)
    else # There are duplicates to insert 
      generate_dup_array(dup_element, dup_count) + f(arr.tail)
    end
  else # Duplicate found, continue with tail of array and increase dup_count
    f(arr.tail, arr.head, dup_count + 1)
  end
end

def generate_dup_array(dup_element, dup_count)
  return [] if dup_count == 0
  (dup_element - dup_count..dup_element).to_a.reverse
end

class Array
  def head; self.first; end
  def tail; self[1..-1]; end
end

p f [211, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200]
# => [211, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190]

p f [10, 8, 5, 5, 7].sort.reverse
# => [10, 8, 7, 5, 4]

p f [9, 6, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2, 1]
# => [9, 6, 5, 5, 4, 4, 3, 3, 2, 1, 2, 1, 1]

答案 2 :(得分:0)

不确定我是否完全理解您的要求,但这是我的尝试:

# Transforms an array of numbers into a sorted array of the same length, where
# each successive element is always smaller than the preceding element.
def force_descending(array)
  array.sort.reverse.each_with_object([]) do |element, collection|
    collection << if collection.empty? || element < collection.last
      element
    else
     collection.last-1
    end
  end
end

示例输入/输出:

force_descending [211, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200]
#=> [211, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190]

force_descending [10, 8, 5, 5, 7]
#=> [10, 8, 7, 5, 4]

force_descending [211, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 196]
#=> [211, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189]

答案 3 :(得分:0)

它已经按降序排列

对于一线人群:

results = numbers.chunk {|num| num}.flat_map {|num, group| (group.length == 1) ? num : ((num - (group.length-1))..num).to_a.reverse}

对于理智的程序员:

numbers = [211, 200, 200, 200]
start_of_dups = "_START_"  #Something not in the array
dup_count = 0

results = numbers.map do |num|
  if start_of_dups == num
    dup_count += 1
    num - dup_count
  else
    dup_count = 0 
    start_of_dups = num
  end
end

p results

--output:--
[211, 200, 199, 198]

但是如果:

array = [10, 10, 10, 9]

--output:--
[10, 9, 8, 9]