Ruby: Хочу подобный Набору объект, который сохраняет порядок

Вы можете просто сделать это в awk, идентифицируя первый файл, который вы используете для справки, и игнорируя его для последующей обработки, используя опцию nextfile (требуется версия GNU), которая пропускает обработку файла для последующей обработки. Исходя из этой логики, вы должны разместить справочный файл, например, file.4.dat в качестве входных данных в качестве первого аргумента в списке файлов.

awk '
BEGIN{ ignoreFile = ARGV[1] }
NR==FNR {
    a[$1]=$2
    next
}
FILENAME == ignoreFile { nextfile }
($1 in a) {
    a[$1]+=$2
}
END {
    for(i in a)
        print i,a[i]
}' file.4.dat file.[1-5].dat >| test.out

ОП хотел знать, могут ли они создать список шаблонов имен файлов, которые можно сгенерировать из оболочки и использовать. Это можно сделать, но, учитывая относительно более простой вариант, доступный в nextfile, это может показаться сложным.

Из вашего понимания у вас есть n файлы, и один из них будет использоваться в качестве справочного файла. Я бы предпочел использовать функцию extglob оболочки bash, чтобы включить все файлы, кроме ссылки. Например, Я создаю файлы file1..10 для объяснения этого

touch file{1..10}
exclude=3

Параметры расширенной оболочки устанавливаются с помощью встроенного shopt

shopt -s extglob
list=(!(file"$exclude"))

. Теперь распечатайте массив, используя declare -p list чтобы увидеть список файлов только с опорным файлом. Теперь используйте массив в вашем awk, как показано ниже. Расширение массива "${list[@]}" приводит к исключению всех файлов, сгенерированных вами выше.

awk ... file"$exclude" "${list[@]}"

8
задан Chowlett 21 April 2009 в 16:11
поделиться

3 ответа

Насколько я знаю, не существует ни одного, и Set по своей математической природе должен быть неупорядоченным (или по крайней мере, на практике это означало не гарантировать порядок - фактически он обычно реализован в виде хеш-таблицы, поэтому он портит порядок).

Тем не менее, нетрудно либо напрямую расширить массив, либо сделать его подклассом для этого. Я только что попробовал, и это работает:

class UniqueArray < Array
  def initialize(*args)
    if args.size == 1 and args[0].is_a? Array then
      super(args[0].uniq)
    else
      super(*args)
    end
  end

  def insert(i, v)
    super(i, v) unless include?(v)
  end

  def <<(v)
    super(v) unless include?(v)
  end

  def []=(*args)
    # note: could just call super(*args) then uniq!, but this is faster

    # there are three different versions of this call:
    # 1. start, length, value
    # 2. index, value
    # 3. range, value
    # We just need to get the value
    v = case args.size
      when 3 then args[2]
      when 2 then args[1]
      else nil
    end

    super(*args) if v.nil? or not include?(v)
  end
end

Кажется, чтобы охватить все основы. Я использовал удобную Ruby Cookbook от OReilly в качестве справочного материала - у них есть рецепт «Обеспечение того, чтобы отсортированный массив оставался отсортированным», что аналогично.

6
ответ дан 5 December 2019 в 06:39
поделиться

You could use a Hash to store the values, and have an incrementing value stored in the value of each Hash pair. Then you can access the set in a sorted manner, albeit slowly, by accessing the objects via their values.

I'll try to add some code in here later to explain further.

I am aware accessing via values is much slower than by keys.

Update 1: In Ruby 1.9, Hash elements are iterated in their insertion order.

1
ответ дан 5 December 2019 в 06:39
поделиться

Не то чтобы я знал об этом, но было бы нетрудно накатить свой собственный. Просто создайте подкласс Array и используйте Set для поддержания ограничения уникальности.

Один вопрос о немом отбрасывании. Как это повлияет на # [] =? Если я пытаюсь перезаписать существующую запись чем-то, что уже было сохранено где-то еще, следует ли в любом случае удалить элемент, который будет удален? Я думаю, что в любом случае в будущем могут возникнуть неприятные сюрпризы.

0
ответ дан 5 December 2019 в 06:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: