Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何修改CSV中的多个列,然后使用Ruby将它们复制到新的CSV?_Ruby_Csv - Fatal编程技术网

如何修改CSV中的多个列,然后使用Ruby将它们复制到新的CSV?

如何修改CSV中的多个列,然后使用Ruby将它们复制到新的CSV?,ruby,csv,Ruby,Csv,在原始CSV中的10列中,我有4列需要生成整数(稍后使用MATLAB进行处理;其他6列已经包含整数值)。这四列分别是:(1)平台(2)推送(3)时间戳和(4)udid 示例输入为:#其他#列,Android,Y,10-05-2015 3:59:59 PM,#其他#列,d0155049772de9,#其他#列 相应的输出应该是:#其他#u列,2,1,1431273612198,#其他#u列,17923,#其他#u列 因此,我编写了以下代码: require 'csv' CSV.open('C:\

在原始CSV中的10列中,我有4列需要生成整数(稍后使用MATLAB进行处理;其他6列已经包含整数值)。这四列分别是:(1)平台(2)推送(3)时间戳和(4)udid

示例输入为:
#其他#列,Android,Y,10-05-2015 3:59:59 PM,#其他#列,d0155049772de9,#其他#列

相应的输出应该是:
#其他#u列,2,1,1431273612198,#其他#u列,17923,#其他#u列

因此,我编写了以下代码:

require 'csv'

CSV.open('C:\Users\hp1\Desktop\Datasets\NewColumns2.csv', "wb") do |csv|
  CSV.foreach('C:\Users\hp1\Desktop\Datasets\NewColumns.csv', :headers=>true).map do |row|

        if row['platform']=='Android'
            row['platform']=2
        elsif row['platform']=='iPhone'
            row['platform']=1
        end


        if row['push']=='Y'
            row['push']=1
        elsif row['push']=='N'
            row['push']=0
        end


        row['timestamp'].to_time.to_i

        row['udid'].to_i

        csv<<row
    end
end
需要“csv”
CSV.open('C:\Users\hp1\Desktop\Datasets\NewColumns2.CSV',“wb”)do | CSV|
CSV.foreach('C:\Users\hp1\Desktop\Datasets\NewColumns.CSV',:headers=>true).映射do |行|
如果行['platform']=='Android'
行['platform']=2
elsif行['platform']=='iPhone'
行['platform']=1
结束
如果行['push']='Y'
行['push']=1
elsif行['push']=='N'
行['push']=0
结束
行['timestamp'].to_time.to_i
第['udid'行]至

csv这是地图的错误用法,这不是您需要的功能。如果要将函数应用于数组中的所有值,并返回数组,则需要映射。您所做的是迭代,进行一些更改,然后将修改后的行推送到一个新数组中-您可以只进行迭代,无需map函数:
CSV.foreach('C:\Users\hp1\Desktop\Datasets\NewColumns.CSV',:headers=>true)
而不是
CSV.foreach('C:\Users\hp1\Desktop\Datasets\NewColumns.CSV',:headers=>true)。map


关于日期,您可以使用strtime将字符串转换为日期:
DateTime.strtime(“10-05-2015 3:59:59 PM”,%d-%m-%Y%l:%m:%S%p”)
。这里的文档:

:converters=>:all
添加到您的选项中,以便自动转换日期和数字。然后,而不是

row['timestamp'].to_time.to_i
进行转换但不将其放置在任何位置(未放置到位),请执行以下操作:

row['timestamp'] = row['timestamp'].to_time.to_i

请注意,这只适用于转换器,否则
行['timestamp']
是一个字符串,没有
.to\u time
方法。

编辑-重做,我遗漏了UDID的部分问题。

问题

  • 当您不需要使用map时,CSV#foreach已经在所有行中进行了迭代-删除此项
  • 日期-包括ruby标准时间库
  • 唯一id-听起来好像您想将udid转换为较短的唯一id,因为每个移动设备可能有多个条目-使用数组创建集合而不重复,并使用数组中设备udid的索引作为新的较短的唯一id
  • 我将此作为输入csv:

    othercol1,platform,push,timestamp,othercol2,udid,othercol3,othercol4,othercol5,othercol6
    11,Android, N, 10-05-2015  3:59:59 PM,22, d0155049772de9,33,44,55,66
    11,iPhone, N, 10-05-2015  5:59:59 PM,22, d0155044772de9,33,44,55,66
    11,iPhone, Y, 10-06-2015  3:59:59 PM,22, d0155049772de9,33,44,55,66
    11,Android, Y, 11-05-2015  3:59:59 PM,22, d0155249772de9,33,44,55,66
    
    这是我的输出csv:

    11,2,0,1431298799,22,1,33,44,55,66
    11,1,0,1431305999,22,2,33,44,55,66
    11,1,1,1433977199,22,1,33,44,55,66
    11,2,1,1431385199,22,3,33,44,55,66
    
    以下是我使用的脚本:

    require 'time' # use ruby standard time library to parse for you
    require 'csv'
    
    udids = [] # turn the udid in to a shorter unique id 
    CSV.open('new.csv', "wb") do |csv|
      CSV.foreach('old.csv', headers: true) do |row|
    
            if row['platform']=='Android'
                row['platform']=2
            elsif row['platform']=='iPhone'
                row['platform']=1
            end
    
            if row['push'].strip =='Y'
                row['push']=1
            elsif row['push'].strip =='N'
                row['push']=0
            end
    
            row['timestamp'] = Time.parse(row['timestamp']).to_i
    
            # turn the udid in to a shorter unique id
            unless udids.include?(row['udid'])
              udids << row['udid']
            end
    
            row['udid'] = udids.index(row['udid']) + 1
    
            csv << row
        end
    end
    
    require'time'#使用ruby标准时间库为您解析
    需要“csv”
    udid=[]#将udid转换为较短的唯一id
    CSV.open('new.CSV',“wb”)do | CSV|
    CSV.foreach('old.CSV',headers:true)do |行|
    如果行['platform']=='Android'
    行['platform']=2
    elsif行['platform']=='iPhone'
    行['platform']=1
    结束
    如果行['push'].strip='Y'
    行['push']=1
    elsif行['push'].条带=='N'
    行['push']=0
    结束
    行['timestamp']=Time.parse(行['timestamp'])。to_i
    #将udid转入一个较短的唯一id
    除非udid.include?(第['udid'行])
    
    UDID欢迎使用堆栈溢出。需要示例输入数据。同时显示您的预期输出。另外,你能把你的代码减少到最低限度并且仍然显示出问题吗?谢谢。为了用裸最小代码表示问题,push列中有两种值-Y&N,我想将Y转换为1,N转换为0。但是这个代码不起作用:
    如果行['push']='Y'
    行['push']=1
    elsif行['push']='N'
    行['push']=0
    结束
    和其他列也有类似的问题,我已经在问题细节中解释过了。我对Ruby很陌生,所以我意识到这可能是一个愚蠢的问题,也许解决方法很简单。不要在评论中解释,编辑你的问题,并将细节添加到问题中,就好像你最初把它们放在那里一样。在评论中加入细节会使问题更难解决。我们需要示例输入和您期望的结果。完成。还添加了示例输入和输出。感谢提供这些信息!但是当我尝试你的建议时,我得到了以下错误:“\u parse”中的
    :没有将nil隐式转换为字符串(TypeError)
    。这用于
    时间戳
    列;其他列将按原样复制,而不首先转换为整数。为什么?谢谢。我试过你的建议;我得到了以下错误:
    未定义nil的“to_time”方法:NilClass(NoMethodError)
    。您能推荐一个解决方案吗?@user5346597一些时间戳列是空白的吗?如果是这样的话,您需要使用类似于
    row['timestamp']=row['timestamp'].to\u time.to\u i,除非row['timestamp'].nil?
    好的,这就行了!但是,新csv不包含修改后的值。它包含与旧csv相同的值,这意味着它们根本没有被转换。如果你能解释一下,为什么会这样?此外,每一行现在包含两个附加列-它们包含
    0
    1
    ,所有行的顺序完全相同。