1

对于我的一个观点,我想包含一个带有 jqueries 预输入功能的搜索字段。

该数组应包含客户端的所有属性值。

查询的数组按以下方式生成:

@clients = []
Client.each do |client|
  @clients << client.attributes.values.join(' ')
end

对于大约 3000 个条目的数据集,这种方法的性能是否足够?还是有更好更快的解决方案?

提前致谢。干杯,帕特里克

更新

一位用户提到要像这样实现它:

@clients = Client.map do |client|
  client.attributes.values.join(' ')
end

这是另一种方法。但是基准测试表明,这并没有提高性能。

这给我留下了一个问题:也许有一种更高效的方式,但说到最多 3000 条记录 - 这真的重要吗?

4

3 回答 3

5

你可以使用.map

@clients = Client.map do |client|
  client.attributes.values.join(' ')
end
于 2013-04-30T10:37:57.720 回答
4

即使 ActiveRecord 模型会实现该map方法(我不相信),OP 和@xdazz 建议的两个解决方案在时间和内存复杂度方面是等效的。这可以通过这个简单的基准来观察:

require 'fruity'

# Dummy client class
class Client < Struct.new(:first_name, :last_name, :position, :company)
  class << self
    include Enumerable

    def each(&block)
      5000.times do
        yield Client.new('Firstname', 'Lastname', 'CEO', 'Company Inc.')
      end
    end
  end

  alias_method :attributes, :to_h
end


compare do
  schnika do
    clients = []
    Client.each do |client|
      clients << client.attributes.values.join(' ')
    end
    nil
  end

  xdazz do
    clients = Client.map do |client|
      client.attributes.values.join(' ')
    end
    nil
  end
end

哪个会输出

schnika is similar to xdazz

此外,当您查看map( 的同义词collect) 的实现时,很明显,除了 OP 的方法之外,没有其他任何事情发生:

static VALUE
rb_ary_collect(VALUE ary)
{
    long i;
    VALUE collect;

    RETURN_ENUMERATOR(ary, 0, 0);
    collect = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
    rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
    }
    return collect;
}

这转化为:

class Array
  def collect
    collect = []
    self.each do |el|
      collect << yield(el)
    end
    collect
  end
end
于 2013-04-30T11:20:09.990 回答
1

您可能不需要检索所有属性(例如 'updated_at'),因此以下可能更快:

@clients = Client.select([:name, :email, :id]).map do |client|
  client.attributes.values.join(' ')
end

添加了id以防万一您需要链接到客户端。

于 2013-04-30T13:57:17.527 回答