Ruby 数组#删除#或数组#切片!?以及如何查找实现

Ruby 数组#删除#或数组#切片!?以及如何查找实现,ruby,arrays,Ruby,Arrays,我正在清理大数据文件(+1MM逗号分隔行)。示例行可能如下所示: @row = "123456789,11122,CustomerName,2014-01-31,2014-02-01,RemoveThisEntry,R,SKUInfo,05-MAR-14 05:50:24,SourceID,RemoveThisEntryToo,TransactionalID" @row = "123456789,11122,CustomerName,2014-01-31,2014-02-01,R,SKUInf

我正在清理大数据文件(+1MM逗号分隔行)。示例行可能如下所示:

@row = "123456789,11122,CustomerName,2014-01-31,2014-02-01,RemoveThisEntry,R,SKUInfo,05-MAR-14 05:50:24,SourceID,RemoveThisEntryToo,TransactionalID"
@row = "123456789,11122,CustomerName,2014-01-31,2014-02-01,R,SKUInfo,05-MAR-14 05:50:24,SourceID,TransactionalID"
必须从中删除某些列,然后该行应如下所示:

@row = "123456789,11122,CustomerName,2014-01-31,2014-02-01,RemoveThisEntry,R,SKUInfo,05-MAR-14 05:50:24,SourceID,RemoveThisEntryToo,TransactionalID"
@row = "123456789,11122,CustomerName,2014-01-31,2014-02-01,R,SKUInfo,05-MAR-14 05:50:24,SourceID,TransactionalID"
问题1:如果我将一行数据转换为
数组
,删除元素时首选哪种方法:或者?我想知道哪一个更为惯用。性能是这里的一个考虑因素,我在一台Windows机器上

def remove_bad_columns
  ary = @row.split(",")
  ary.delete_at(10)
  ary.delete_at(5)
  @row = ary.join(",")
end

问题2:我想知道这些方法中是否有一种是用另一种实现的。我怎样才能看到这些方法是如何在ruby中构建的?(例如,如何使用
每个
来实现

在性能上并没有什么差别。我更喜欢在
处删除,因为这样读起来更好

require 'benchmark'

def array
  "123456789,11122,CustomerName,2014-01-31,2014-02-01,RemoveThisEntry,R,SKUInfo,05-MAR-14 05:50:24,SourceID,RemoveThisEntryToo,TransactionalID"
end 

def delete_at
  ary = array.dup.split(",")
  ary.delete_at(10)
  ary.delete_at(5)
  @row = ary.join(",")
end

def slice!
  ary = array.dup.split(",")
  ary.slice!(10)
  ary.slice!(5)
  @row = ary.join(",")
end

require 'benchmark'

n = 1_000_000
Benchmark.bmbm(15) do |x|
  x.report("delete_at :")   { n.times do; delete_at; end }
  x.report("slice!    :")   { n.times do; slice!   ; end }
end

# Rehearsal ---------------------------------------------------
# delete_at :       4.560000   0.000000   4.560000 (  4.566496)
# slice!    :       4.580000   0.010000   4.590000 (  4.576767)
# ------------------------------------------ total: 9.150000sec
# 
#                       user     system      total        real
# delete_at :       4.500000   0.000000   4.500000 (  4.505638)
# slice!    :       4.600000   0.000000   4.600000 (  4.613447)
我建议您使用而不是
删除
切片

def remove_vals(str, *indices)
  ary = str.split(",")
  v = (0...ary.size).to_a - indices
  ary.values_at(*v).join(",")
end

@row = "123456789,11122,CustomerName,2014-01-31,2014-02-01,RemoveThisEntry," +
      "R,SKUInfo,05-MAR-14 05:50:24,SourceID,RemoveThisEntryToo,TransactionalID"

@row = remove_vals(@row, 5, 10)
  #=> "123456789,11122,CustomerName,2014-01-31,2014-02-01,R,SKUInfo," +
  #   "05-MAR-14 05:50:24,SourceID,TransactionalID"
Array#values_at
与其他两种方法相比具有优势,您不必担心删除元素的顺序

这种方法的效率与其他两种方法没有显著差异。如果@spickermann希望将其添加到基准测试中,他可以使用以下方法:

def values_at
  ary = array.split(",")
  v = (0...ary.size).to_a - [5,10]
  @row = ary.values_at(*v).join(",")
end

处理CSV数据时应该使用Ruby。如果速度很重要,命令行工具通常会更快:
cut-d“,“-f1-5,7-10,12 largedatafile.csv
性能在这里很重要,因为查看一年(或更长)的观察结果时,文件可能包含+6MM行。(我应该在问题中提到这一点。)我在第一次使用时也尝试过使用
CSV
库(因为你肯定是对的),但是脚本一直被数据中令人讨厌的工件绊倒——在通过字符串操作进行了这么多Santize之后,我想我会一直坚持使用字符串。我没有考虑过像
cut
这样的*nix实用程序,现在正在下载
cygwin
来尝试一下。谢谢您可以随时翻阅MRI Ruby代码。它是开放的,它将允许您查看如何在较低级别上实现。准备好阅读MRI Ruby中的C:),数组切片
由函数实现,在这种情况下,您只传递一个要删除的索引
rb_ary_delete_at
是最终实现
Array#delete_at
的函数,通过该函数,只需将参数从Ruby对象转换为C“long”。如果您的列包含嵌入逗号,如果您尝试使用像
split(',')
这样简单的方法进行拆分,您将很快陷入困境。CSV将处理简单代码无法处理的条件。我在
中选择了
delete\u以提高可读性,哈哈。谢谢你也做了基准测试-你认为它们的相似性意味着一个是根据另一个来实现的吗?在
上没有方法
deleted\u。这是一个非常棒的策略,在一个小测试中像gangbusters一样工作-谢谢!正在使用的
值\u已添加到我的待办事项列表中。。。