Ad2ffc6b05fb4390643f36a258b86362

This is not really a refactoring as much as a request of solution for my problem.

The problem is: I'd like some ruby-ish way of returning an array of keys-next-to-character. For instance: passing "b" would return v,n,h,g (the keys next to b on a keyboard)

The solution i have on my mind needs to create some kind of big hash with all the keys, but there must a better way?

1
2
3
4
5
6
7
keys = {
  "a" => %w(q w s z),
  "b" => %w(v n g h),
  "c" => %w(x d f v)
  ...
}
p keys["b"]

Refactorings

No refactoring yet !

429d95962c6ae646c107a812bfc49a9d

Joran Jessurun

October 23, 2007, October 23, 2007 14:28, permalink

No rating. Login to rate!

This is my attempt. Not really ruby like but more a general solution.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@keyboard_layout = [
  "1234567890-=",
  "qwertyuiop[]",
  "asdfghjkl;'",
  "zxcvbnm,./",
]

def key_coordinates(key)
  @keyboard_layout.each_with_index do |line, i|
    return [line.index(key), i] if line.include?(key)
  end
  [nil, nil]
end

def get_key(x, y)
  return nil if y < 0 || y >= @keyboard_layout.size
  line = @keyboard_layout[y]
  return nil if x < 0 || x > line.size
  line[x..x]
end

def keys_around(key)
  x, y = key_coordinates(key)
  if x && y
    [ 
      get_key(x - 1, y), get_key(x - 1, y + 1),
      get_key(x, y - 1), get_key(x, y + 1),
      get_key(x + 1, y - 1), get_key(x + 1, y)
    ].compact
  end
end

p keys_around('b')
5392d0a82eb7a8d8c6246f9dbbc2244a

Scott Patten

October 23, 2007, October 23, 2007 17:14, permalink

No rating. Login to rate!

Here it is. That would make a good Ruby Quiz. You should submit it.

You may disagree with my definition of neighbours, I didn't include punctuation as neighbours, and this will only work on a North American keyboard as is, but it seems to work.

To use it, require this file, and then call something like

Keyboard.neighbours('f')

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env ruby

class Keyboard
  QWERTY = [ "qwertyuiop".split(''), "asdfghjkl".split(''), "zxcvbnm".split('')]
  
  def initialize(char)
    @char = char
  end
  
  def neighbours
    (row_neighbours + row_above_neighbours + row_below_neighbours).sort.join
  end
  
  def Keyboard.neighbours(char)
    Keyboard.new(char).neighbours
  end
  
  private
  def row
     QWERTY.detect {|row| row.include?(@char)}
  end
  
  def row_above
    QWERTY[row_num - 1] if row_num() -1 >= 0
  end
  
  def row_below
    QWERTY[row_num + 1] if row_num() + 1 < QWERTY.length
  end
  
  def row_num
    QWERTY.index(row)    
  end
  
  def in_row_index
    row.index(@char)
  end
  
  def select_from_row(row_string, indices)
    return [] unless row_string
    indices.collect {|n| row_string[n .. n] if n >= 0 and n < row_string.length}.compact.sort
  end
  
  def row_neighbours    
    select_from_row(row, [in_row_index() - 1, in_row_index() + 1])
  end
  
  def row_above_neighbours
    select_from_row(row_above, [in_row_index() , in_row_index() + 1 ])
  end
  
  def row_below_neighbours
    select_from_row(row_below, [in_row_index() -1, in_row_index() ])
  end  
end

require 'test/unit'

class KeyboardNeighboursTest < Test::Unit::TestCase
  
  def test_neighbours
    expected_neighbours = {'q'=> 'aw', 't' => 'fgry', 'i' => 'jkou', 'p' => 'lo', 'a' => 'qswz', 
                           'f' => 'cdgrtv', 'j' => 'hikmnu', 'l' => 'kop', 'z' => 'asx', 'v' => 'bcfg',
                           'n' => 'bhjm', 'm' => 'jkn'}
    expected_neighbours.each do |key, neighbours|
      assert_equal neighbours, Keyboard.neighbours(key)
    end
  end
end
B8d457d2c39911ea4c74ba7d66b9c3f7

Marco Valtas

October 24, 2007, October 24, 2007 02:45, permalink

No rating. Login to rate!

Hi, I don't how to write a Ruby solution but you can have some idea looking at this Perl module.

http://search.cpan.org/~krburton/String-KeyboardDistance-1.01/KeyboardDistance.pm

Your refactoring





Format Copy from initial code

or Cancel