按子数组总大小将子数组拆分为Ruby

如何解决按子数组总大小将子数组拆分为Ruby

我有一个子数组数组:

arr = [["a","b","c"],["a","b"],["c","v"],"f"],["e","a"],"n","m"],"c","g"]]

我想将每个子数组的元素放到另一个数组中,但是子数组的总和必须小于或等于6。所以我想得到类似这样的东西

[["a","a","v","f","e","m","g"]]

我现在的代码是

stop = 0
new_arr = []
indexo = ""
arr.each_with_index do |x,index|
   stop = stop + x.size
   if stop <= 6
      new_arr << x
      indexo = index
   end
end

我被困在这里,因为我的代码仅包含两个前元素。原始数组大约有1000个子数组,而我的代码并未将其拆分为这种形式。

解决方法

您可以使用reduce方法并继续将子数组推入新数组。请考虑以下内容:

new_arr = arr.reduce([]) do |acc,sub_array|
  last_element = acc[acc.length - 1]

  if last_element.nil? or (last_element + sub_array).length > 6
    acc << sub_array
  else
    acc[acc.length - 1] = last_element + sub_array
  end
  acc
end

# Tests
new_arr.flatten.size == arr.flatten.size # test total number of elements in both the arrays
new_arr.map(&:size) # the sizes of all sub arrays
new_arr.map(&:size).min # min size of all sub arrays
new_arr.map(&:size).max # max size of all sub arrays

让我知道代码是否不清楚

更新

Reduce方法将通过遍历可枚举的每个元素来将任何可枚举的对象“还原”为单个值,就像eachmap

考虑一个例子:

# Find the sum of array
arr = [1,2,3]

# Reduce will accept an initial value & a block with two arguments
#   initial_value: is used to set the value of the accumulator in the first loop

#   Block Arguments:
#   accumulator: accumulates data through the loop and finally returned by :reduce
#   value: each item of the above array in every loop(just like :each)

arr.reduce(0) do |acc,value|
  # initial value is 0; in the first loop acc's value will be set to 0
  # henceforth acc's value will be what is returned from the block in every loop

  acc += value
  acc # acc is begin returned; in the second loop the value of acc will be (0 + 1)
end

因此,在这种情况下,在每个循环中,我们将该项的值添加到累加器中,并返回累加器以在下一个循环中使用。一旦reduce迭代了数组中的所有项目,它将返回累加器。

Ruby还提供了语法糖以使其看起来更漂亮:

arr.reduce(:+) # return 6

很好article,以供进一步参考

因此,如果您以问题为例:

# Initial value is set to an empty array,what we're passing to reduce
new_arr = arr.reduce([]) do |acc,sub_array|
  # In the first loop acc's value will be set to []

  # we're finding the last element of acc (in first loop since the array is empty
  #    last element will be nil)
  last_element = acc[acc.length - 1]

  # If last_element is nil(in first loop) we push the first item of the array to acc
  # If last_element is found(pushed in the previous loops),we take it and sum
  #    it with the item from the current loop and see the size,if size is more
  #    than 6,we only push the item from current loop
  if last_element.nil? or (last_element + sub_array).length > 6
    acc << sub_array
  else
    # If last element is present & last_element + item from current loop's size
    #    is less than 6,we push the (last_element + item from current loop) into 
    #    the accumulator.
    acc[acc.length - 1] = last_element + sub_array
  end

  # Finally we return the accumulator,which will be used in the next loop
  # Or if has looped through the entire array,it will be used to return back
  #    from where it was called
  acc
end
,
arr = [["a","b","c"],["a","b"],["c","v"],"f"],["e","a"],"n","m"],"c","g"]]
arr.each_with_object([[]]) do |a,ar|
  if a.size + ar[-1].size > 6
    ar << a
  else
    ar[-1] += a
  end
end
  #=> [["a","a",#    ["c","v","f","e",#    ["a","m","g"]]

步骤如下。

enum = arr.each_with_object([[]])
  #=> #<Enumerator: [["a",...
  #     ["a","g"]]:each_with_object([[]])>

第一个值是由该枚举数生成的,并传递到块中,并且通过将Array Decomposition应用于传递到该块的两元素数组来为块值分配值。

a,ar = enum.next
   #=> [["a",[[]]] 
a  #=> ["a","c"] 
ar #=> [[]] 

请参见Enumerator#next。然后评估条件语句。

a.size + ar[-1].size > 6
  #=> 3 + 0 > 6 => false

所以我们执行:

ar[-1] += a
   #=> ["a","c"] 
ar #=> [["a","c"]]

下一个元素由enum生成,传递到块,并为块值分配值。

a,[["a","c"]]] 
a  #=> ["a","b"] 
ar #=> [["a","c"]]

条件语句被评估。

a.size + ar[-1].size > 6
  #=> 2 + 3 > 6 => false

所以我们再次执行:

ar[-1] += a
   #=> ["a","b"]]

enum然后将第三个元素传递到块。

a,"b"]]] 
a  #=> ["a","b"]] 

因为:

a.size + ar[-1].size > 6
  #=> 3 + 5 > 6 => false

这次我们执行

ar << a
  #=> [["a","c"]] 

其余步骤相似。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?