代码之家  ›  专栏  ›  技术社区  ›  Garry Shutler

在这种情况下使用collect是否更好?

  •  1
  • Garry Shutler  · 技术社区  · 16 年前

    我刚刚开始使用Ruby,我已经编写了一些代码来对CSV文件进行基本解析(Line是一个基本类,为简洁起见省略):

    class File
    
      def each_csv
        each do |line|
          yield line.split(",")
        end
      end
    
    end
    
    lines = Array.new
    
    File.open("some.csv") do |file|
      file.each_csv do |csv| 
        lines << Line.new(:field1 => csv[0], :field2 => csv[1])
      end
    end
    

    我有一种感觉,如果使用 collect Line

    有人能告诉我怎么做吗?还是说它现在很好?

    我应该清楚地表明,我实际上不打算在生产中使用这段代码,而是要习惯语言的结构。不过,知道有一些库可以正确地执行此操作仍然很有用。

    4 回复  |  直到 16 年前
        1
  •  4
  •   Dominik Grabiec    16 年前

    这里有一个(可能很疯狂的)想法,使用Struct类而不是滚动您自己的简单POD类。但是您希望从中得到一个构造函数,它接受可以从文件数据生成的所有参数。

    Line = Struct.new(:field1, :field2, :field3)
    

    然后,在算法的核心,您需要如下内容:

    File.open("test.csv").lines.inject([]) do |result, line|
        result << Line.new(line.split(",", Line.length))
    end
    

    lines = File.open("test.csv").lines.map { |line| Line.new(line.split(",", Line.length)) }
    

    老实说,我没有太多地使用Struct类,但我应该这么做,而且我可能会重构已经编写好使用它的东西。它允许您通过名称访问变量,如:

    Line.field1 = blah
    Line.field2 = 1
    

    红宝石 Struct

    所以 ,并且查看上面的代码,我会说使用collect/map来执行计算要简单得多。map函数和inject都非常强大,我发现我经常使用它们。

        2
  •  2
  •   georg    16 年前

    我不知道你是否知道,但ruby知道 it's own class 用于解析和写入CSV文件。

    def csv_to_array(file_location)
      csv = CSV::parse(File.open(file_location, 'r') {|f| f.read })
      fields = csv.shift
      csv.collect { |record| Hash[*(0..(fields.length - 1)).collect {|index| [fields[index],record[index].to_s] }.flatten ] }
    end
    

    这个例子取自 this article .

    如果您不熟悉*概念,它基本上会分解外部的[]括号,将数组转换为以逗号分隔的元素列表。

        3
  •  1
  •   aussiegeek    16 年前

        4
  •  0
  •   Stefan Mai    16 年前

    看看这对你是如何起作用的(函数式编程很有趣!)

    尝试使用inject。Inject将启动“累加器”作为参数,然后是一个双参数块:

    [1,2,3].inject(0) { |sum,num| sum+num }
    

    自然是6岁

    [1,2,3].inject(5) { |sum,num| sum+num }
    

    是11岁

    [1,2,3].inject(2) { |sum,num| sum*num }
    

    切中要害:

    class Line
      def initialize(options)
        @options = options
      end
    
      def to_s
        @options[:field1]+" "+@options[:field2]
      end
    end
    
    File.open("test.csv").lines.inject([]) do |lines,line|
      split = line.split(",")
      lines << Line.new(:field1 => split[0],:field2 => split[1])
    end