2012-02-23 77 views
6

Tôi có một Mảng và muốn chèn một phần tử mới vào giữa tất cả các phần tử, cách nào đó giống như phương thức join. Ví dụ, tôi cóLàm thế nào để chèn một phần tử mới vào giữa tất cả các phần tử của một mảng Ruby?

[1, [], "333"] 

và những gì tôi cần là

[1, {}, [], {}, "333"] 

Lưu ý một hash trống mới được chèn vào giữa tất cả các yếu tố.

Edit: Hiện nay những gì tôi có là:

irb(main):028:0> a = [1, [], "333"] 
=> [1, [], "333"] 
irb(main):029:0> a = a.inject([]){|x, y| x << y; x << {}; x} 
=> [1, {}, [], {}, "333", {}] 
irb(main):030:0> a.pop 
=> {} 
irb(main):031:0> a 
=> [1, {}, [], {}, "333"] 
irb(main):032:0> 

Tôi muốn biết cách tốt nhất.

+0

'x.push (y, {})' ngắn hơn, cả mảng '' 'và' push', vì vậy bạn không cần '; x',' inject' là chậm –

Trả lời

14
[1, 2, 3].flat_map { |x| [x, :a] }[0...-1] 
#=> [1, :a, 2, :a, 3] 

FYI, chức năng đó được gọi là intersperse (ít nhất trong Haskell).

[Cập nhật] Nếu bạn muốn tránh những lát (đã tạo ra một bản sao của mảng):

[1, 2, 3].flat_map { |x| [x, :a] }.tap(&:pop) 
#=> [1, :a, 2, :a, 3] 
+0

Tôi sẽ không làm '[0 ..- 1]' trong Haskell (và có lẽ trong Ruby quá) –

+0

@VictorMoroz, bạn sẽ làm gì thay thế? –

+0

@VictorMoroz: Đã thêm đoạn mã vào. Ruby không có trừu tượng cho điều này, vì vậy tôi đã sử dụng tap + pop. – tokland

1
a = [1,2,3] 
h, *t = a 
r = [h] 
t.each do |e| 
    r.push({}, e) 
end 
r #=> [1, {}, 2, {}, 3] 
1

Bạn có thể làm một cái gì đó như:

a = [1, [], "333"] 
new_a = a.collect {|e| [e, {}]}.flatten(1) 
=> [1, {}, [], {}, "333", {}] 

Bạn cần phải làm .flatten(1) bởi vì nó sẽ làm phẳng mảng trống của bạn mà không có nó.

Hoặc như @David Grayson nói trong nhận xét, bạn có thể làm một số flat_map sẽ thực hiện tương tự.

a.flat_map {|e| [e, {}]} 
=> [1, {}, [], {}, "333", {}] 

@tokland có câu trả lời đúng nếu {} cuối cùng không cần thiết. Bạn trả lại một lát từ 0 đến độ dài - 1 hoặc [0..-1].

+1

Phiên bản ngắn hơn: ' a.flat_map {| e | [e, {}]} ' –

+0

Ồ, đẹp quá! Và nó không làm phẳng mảng trống. Cuộc gọi tốt. Chỉ cần –

+1

mới nhất '{}' không được yêu cầu –

0
irb(main):054:0* [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(1).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, "XXX", 2, "XXX", 3, "XXX", 4, "XXX", 5, "XXX", 6, "XXX", 7, "XXX", 8, "XXX", 9] 
irb(main):055:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(2).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, 2, "XXX", 3, 4, "XXX", 5, 6, "XXX", 7, 8, "XXX", 9] 
irb(main):056:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(3).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, 2, 3, "XXX", 4, 5, 6, "XXX", 7, 8, 9] 
irb(main):057:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(4).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, 2, 3, 4, "XXX", 5, 6, 7, 8, "XXX", 9] 
irb(main):058:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(5).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, 2, 3, 4, 5, "XXX", 6, 7, 8, 9] 
irb(main):059:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(6).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, 2, 3, 4, 5, 6, "XXX", 7, 8, 9] 
irb(main):060:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(7).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, 2, 3, 4, 5, 6, 7, "XXX", 8, 9] 
irb(main):061:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(8).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, 2, 3, 4, 5, 6, 7, 8, "XXX", 9] 
irb(main):062:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(9).flat_map {|e| e << "XXX"}[0...-1] 
=> [1, 2, 3, 4, 5, 6, 7, 8, 9] 
irb(main):063:0> 
0

Một số khác đó là tương tự như Tokland của:

xs.inject([]){|x,y| x << y << {}}[0...-1] 
1

Một tương tự giải pháp sử dụng #product:

[1, 2, 3].product([{}]).flatten(1)[0...-1] 
# => [ 1, {}, 2, {}, 3 ] 
0

Một cách tiếp cận là để zip khác mảng của các yếu tố cần thiết rồi san bằng nó với depth = 1:

> arr = [1, [], "333"] 
> element = {} 
> interspersed = arr.zip([element] * (arr.size - 1)).flatten(1).compact 
> # [1, {}, [], {}, "333" ] 

Bạn có thể mở rộng Array để làm cho hành vi này dễ tiếp cận hơn.

class Array 
    def intersperse(elem) 
    self.zip([elem] * (self.size - 1)).flatten(1).compact 
    end 
end 

ví dụ

[43] nâng lên (chính)> [1,2,3].vãi ra ('a')
=> [1, "a", 2, "a", 3]

0
[1, 2, 3, 4, 5].inject { |memo, el| Array(memo) << {} << el } 
#=> [1, {}, 2, {}, 3, {}, 4, {}, 5] 

inject sẽ sử dụng các yếu tố đầu tiên để bắt đầu, do đó bạn không cần gây rối với các chỉ số.

Các vấn đề liên quan