I have an array of strings. I'm wanting to change the name of these duplicate strings to append a numerical value to make them unique like so...
我有一个字符串数组。我想更改这些重复字符串的名称,添加一个数值,使它们具有惟一性,比如……
Original Array
原始数组
a, a, A, b, c, D, d
Corrected Array
纠正数组
a, a1, A2, b, c, D, d1
I've gotten close to this with the following code; however, if the strings are a different case structure then they aren't currently considered duplicates with this code snippet. I would like them to be considered duplicates, but yet not change their case in the results array.
我已经用下面的代码接近了这一点;但是,如果字符串是不同的大小写结构,则当前不认为它们与此代码片段是重复的。我希望它们被认为是重复的,但在结果数组中并没有改变它们的情况。
duplicate_counter = 1
duplicates = Array.new
duplicates = file_columns.select{ |e| file_columns.count(e) > 1 } # get duplicate column names
duplicates.each{ |x| file_columns.delete(x) }
duplicates.sort!
duplicates.each_with_index do |d, i|
if i > 0
if d == duplicates[i-1]
d = d.strip + duplicate_count.to_s
duplicate_count += 1
else
duplicate_count = 1
end
end
# Add back the column names, but with the appended numerical counts to make them unique
file_columns.push(d)
end
2 个解决方案
#1
3
You are over thinking it considerably. I'm sure there are better ways to do this as well, but it gets the job done.
你想得太多了。我相信有更好的方法可以做到这一点,但它确实完成了任务。
a = ['a', 'a', 'A', 'b', 'c', 'D', 'd']
letters = Hash.new(-1)
a.map do |letter|
l = letter.downcase
letters[l] += 1
if (letters[l] > 0)
"#{letter}#{letters[l]}"
else
"#{letter}"
end
end
#2
1
Here's a way to do it if letters independent of case are not necessarily grouped. For example, it will convert this array:
这是一种方法,如果独立于案例的字母不一定是分组的。例如,它将转换这个数组:
arr = %w{ a D a A b c D a d }
#=> ["a", "D", "a", "A", "b", "c", "D", "a", "d"]
to:
:
["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]
Code
代码
def convert(arr)
arr.each_with_index
.group_by { |c,_| c.downcase }
.values
.flat_map { |c|
c.map
.with_index { |(f,l),i| [i > 0 ? f<<i.to_s : f, l] } }
.sort_by(&:last)
.map(&:first)
end
Example
例子
For arr
above:
arr上面:
convert(arr)
#=> ["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]
Explanation
解释
Dear reader, if you are new to Ruby, this may look impossibly complex. If you break it down into steps, however, it's not that bad. After you gain experience and become familiar with commonly-used methods, it will come quite naturally. Here I've used the following methods, chained together so that the return value of each becomes the receiver of the next:
亲爱的读者,如果你是Ruby新手,这看起来可能非常复杂。但是,如果你把它分解成几个步骤,就没那么糟糕了。在你获得经验并熟悉了常用的方法之后,它就会自然而然地出现。这里我使用了以下方法,将它们链接在一起,使每个方法的返回值成为下一个方法的接收者:
- Enumerable#each_with_index
- 可列举的# each_with_index
- Enumerable#group_by
- 可列举的# group_by
- Hash#values
- 哈希值#
- Enumerable#flat_map
- 可列举的# flat_map
- Enumerable#sort_by
- 可列举的# sort_by
- Enumerable#first
- 可列举的#第一
Here's what's happening.
这是发生了什么。
enum = arr.each_with_index
#=> #<Enumerator: ["a", "D", "a", "A", "b", "c",
# "D", "a", "d"]:each_with_index>
h = enum.group_by { |c,_| c.downcase }
#=> {"a"=>[["a", 0], ["a", 2], ["A", 3], ["a", 7]],
# "d"=>[["D", 1], ["D", 6], ["d", 8]],
# "b"=>[["b", 4]],
# "c"=>[["c", 5]]}
a = h.values
#=> [[["a", 0], ["a", 2], ["A", 3], ["a", 7]],
# [["D", 1], ["D", 6], ["d", 8]],
# [["b", 4]],
# [["c", 5]]]
b = a.flat_map { |c| c.map.with_index { |(f,l),i| [i > 0 ? f<<i.to_s : f, l] } }
#=> [["a", 0], ["a1", 2], ["A2", 3], ["a3", 7], ["D", 1],
# ["D1", 6], ["d2", 8], ["b", 4], ["c", 5]]
c = b.sort_by(&:last)
#=> [["a", 0], ["D", 1], ["a1", 2], ["A2", 3], ["b", 4],
# ["c", 5], ["D1", 6], ["a3", 7], ["d2", 8]]
c.map(&:first)
#=> ["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]
#1
3
You are over thinking it considerably. I'm sure there are better ways to do this as well, but it gets the job done.
你想得太多了。我相信有更好的方法可以做到这一点,但它确实完成了任务。
a = ['a', 'a', 'A', 'b', 'c', 'D', 'd']
letters = Hash.new(-1)
a.map do |letter|
l = letter.downcase
letters[l] += 1
if (letters[l] > 0)
"#{letter}#{letters[l]}"
else
"#{letter}"
end
end
#2
1
Here's a way to do it if letters independent of case are not necessarily grouped. For example, it will convert this array:
这是一种方法,如果独立于案例的字母不一定是分组的。例如,它将转换这个数组:
arr = %w{ a D a A b c D a d }
#=> ["a", "D", "a", "A", "b", "c", "D", "a", "d"]
to:
:
["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]
Code
代码
def convert(arr)
arr.each_with_index
.group_by { |c,_| c.downcase }
.values
.flat_map { |c|
c.map
.with_index { |(f,l),i| [i > 0 ? f<<i.to_s : f, l] } }
.sort_by(&:last)
.map(&:first)
end
Example
例子
For arr
above:
arr上面:
convert(arr)
#=> ["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]
Explanation
解释
Dear reader, if you are new to Ruby, this may look impossibly complex. If you break it down into steps, however, it's not that bad. After you gain experience and become familiar with commonly-used methods, it will come quite naturally. Here I've used the following methods, chained together so that the return value of each becomes the receiver of the next:
亲爱的读者,如果你是Ruby新手,这看起来可能非常复杂。但是,如果你把它分解成几个步骤,就没那么糟糕了。在你获得经验并熟悉了常用的方法之后,它就会自然而然地出现。这里我使用了以下方法,将它们链接在一起,使每个方法的返回值成为下一个方法的接收者:
- Enumerable#each_with_index
- 可列举的# each_with_index
- Enumerable#group_by
- 可列举的# group_by
- Hash#values
- 哈希值#
- Enumerable#flat_map
- 可列举的# flat_map
- Enumerable#sort_by
- 可列举的# sort_by
- Enumerable#first
- 可列举的#第一
Here's what's happening.
这是发生了什么。
enum = arr.each_with_index
#=> #<Enumerator: ["a", "D", "a", "A", "b", "c",
# "D", "a", "d"]:each_with_index>
h = enum.group_by { |c,_| c.downcase }
#=> {"a"=>[["a", 0], ["a", 2], ["A", 3], ["a", 7]],
# "d"=>[["D", 1], ["D", 6], ["d", 8]],
# "b"=>[["b", 4]],
# "c"=>[["c", 5]]}
a = h.values
#=> [[["a", 0], ["a", 2], ["A", 3], ["a", 7]],
# [["D", 1], ["D", 6], ["d", 8]],
# [["b", 4]],
# [["c", 5]]]
b = a.flat_map { |c| c.map.with_index { |(f,l),i| [i > 0 ? f<<i.to_s : f, l] } }
#=> [["a", 0], ["a1", 2], ["A2", 3], ["a3", 7], ["D", 1],
# ["D1", 6], ["d2", 8], ["b", 4], ["c", 5]]
c = b.sort_by(&:last)
#=> [["a", 0], ["D", 1], ["a1", 2], ["A2", 3], ["b", 4],
# ["c", 5], ["D1", 6], ["a3", 7], ["d2", 8]]
c.map(&:first)
#=> ["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]