dreader 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaf2760d6b154eed0557f71a3485c1ee25b16d378f0e9e39ad4e32f2b179fc6d
4
- data.tar.gz: 03c06359c7b7db68585501ff171f020037358ee5cc98bed4fd3047ce68e964f6
3
+ metadata.gz: a59b3e8b84e9bd26d753db6e25ff23158ecc6e64dc16eb61c37b3f49434f06b2
4
+ data.tar.gz: a68e6045cce69837e779a85981b2f09feba3c868508abc65e806132786542cde
5
5
  SHA512:
6
- metadata.gz: eb6bfca19ddb2f7e35ae46fc19c20453b24e85d03f820b692d76743d3a835edc7addc974ff3a0a1e51f7dd90356c27b7ab83675105c850326f9d8d0320798535
7
- data.tar.gz: 97736d7edf259fcbfcc0338c5a94cff108a2c2ec2f1e48b3d205714e3391fe7cd5b0a61d6a6a95a15cc6a795295dbb14ee2a32bc480c4c095a31313afbe2f80d
6
+ metadata.gz: 5c2aae8a2439807827513eca2f20f8c1124849477e48b87133379a702f34157e729b964450b5f2ac3104583ef92a4a21f9022824d0bd6f865e9ed7824455545b
7
+ data.tar.gz: 9ed0f9b735bd3f1ae75ff46fe1509d37c15f2458e064612cd1909e4be65f11654beaaac2a807d1f7f6ef5962e81925848136bcf80c8eddecafb026b07d5ee5b1
data/.gitignore CHANGED
@@ -6,3 +6,4 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ *~
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dreader (0.2.0)
5
+ roo
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ mini_portile2 (2.3.0)
11
+ nokogiri (1.8.2)
12
+ mini_portile2 (~> 2.3.0)
13
+ rake (10.5.0)
14
+ roo (2.7.1)
15
+ nokogiri (~> 1)
16
+ rubyzip (~> 1.1, < 2.0.0)
17
+ rubyzip (1.2.1)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ bundler (~> 1.16)
24
+ dreader!
25
+ rake (~> 10.0)
26
+
27
+ BUNDLED WITH
28
+ 1.16.1
data/README.md CHANGED
@@ -1,19 +1,32 @@
1
1
  # Dreader
2
2
 
3
- A simple DSL built on top of `roo` to read and process tabular data (CSV,
4
- LibreOffice, Excel).
3
+ A simple DSL built on top of [Roo](https://github.com/roo-rb/roo) to
4
+ read and process tabular data (CSV, LibreOffice, Excel).
5
5
 
6
- Use this gem to specify the structure of some tabular data you want to
7
- process. The input data can be in CSV, LibreOffice, and Excel. Each row can
8
- then be passed to a block of code you define.
6
+ This gem allows you to:
9
7
 
10
- The gem can thus be used to check, process, import data. We use it to import data into
11
- Rails application, but the gem can used in any Ruby application.
8
+ 1. specify the structure of some tabular data you want to process
9
+ 2. debug and check correctness of the data you read
10
+ 3. read a file and process it, that is, execute code for each cell and
11
+ each row of the file
12
12
 
13
- The gem should be relatively easy to use, despite its name: *dread* stands for
14
- *d*ata *r*eader.
13
+ If your data require elaborations which cannot be performed line by
14
+ line, you can also access all the data read by the gem and manipulate
15
+ it as you need.
16
+
17
+ The input data can be in CSV (comma or tab separated), LibreOffice,
18
+ and Excel.
19
+
20
+ We use it to import data into Rails application, but the gem can used
21
+ in any Ruby application.
22
+
23
+ The gem should be relatively easy to use, despite its name: *dread*
24
+ stands for *d*ata *r*eader.
25
+
26
+ The gem depends on `roo`, from which we leverage all data
27
+ reading/parsing facilities and which allows us to achieve what we want
28
+ in about 250 lines of code.
15
29
 
16
- The gem depends on `roo`.
17
30
 
18
31
  ## Installation
19
32
 
@@ -33,61 +46,245 @@ Or install it yourself as:
33
46
 
34
47
  ## Usage
35
48
 
36
- ```
49
+ Require `dreader` and declare an instance of the `Dreader::Engine` class:
50
+
51
+ ```ruby
52
+ require 'dreader'
53
+
37
54
  i = Dreader::Engine.new
55
+ ```
38
56
 
57
+ Specify parsing option, using the following syntax:
58
+
59
+ ```ruby
39
60
  i.options do
40
- start_at 1
61
+ filename 'example.ods'
62
+
63
+ sheet 'Sheet 1'
64
+
65
+ first_row 1
66
+ last_row 20
41
67
  end
68
+ ```
69
+
70
+ where:
71
+
72
+ * (optional) `filename` is the file to read. If not specified, you
73
+ will have to supply a filename when loading the file. The extension
74
+ determines the file type. **Use `tsv` for tab-separated files.**
75
+ * (optional) `first_row` is the first line to read (use `2` if your
76
+ file has a header)
77
+ * (optional) `last_row` is the last line to read. If not specified, we
78
+ will rely on `roo` to determine the last row
79
+ * (optional) `sheet` is the sheet name or number to read from. If not
80
+ specified, the first (default) sheet is used
81
+
82
+ Spexcify the structure of your file, for the columns you are interested
83
+ to process. You have to specify a name (used to access data) and a
84
+ column reference (used to read data from the file).
85
+
86
+ You can also specify two ruby blocks, `process` and `check` to
87
+ preprocess data and to check for errors.
42
88
 
43
- # first column is called name
89
+ For instance, given the following file:
90
+
91
+ | Name | Surname | Age |
92
+ | John | Doe | 30 |
93
+ | Jane | Doe | 31 |
94
+ | ... | ... | ... |
95
+
96
+ we could use the following declaration to specify the data to read:
97
+
98
+ ```ruby
99
+ # we want to access column 1 using :name
44
100
  # :name should be non nil and of length greater than 0
45
101
  i.column :name do
102
+ colref 1
46
103
  check do |x|
47
104
  x and x.length > 0
48
105
  end
49
106
  end
50
107
 
51
- # second column is called surname
52
- # :surname should be non nil and of length greater than 0
53
- i.column :surname do
108
+ # we want to access column 3 (Age) using :age
109
+ # :age should be non nil and of length greater than 0
110
+ i.column :age do
111
+ colref 3
112
+
113
+ # make sure the column is transformed into an integer
114
+ process do |x|
115
+ x.to_i
116
+ end
117
+
118
+ # check age is defined and greater than zero
54
119
  check do |x|
55
120
  x and x.length > 0
56
121
  end
57
- end
122
+ end
58
123
 
59
- # third column is called birthdate
60
- # :name should be non nil and of length greater than 0
61
- i.column :birthdate do
62
- check do |x|
63
- x.class == Date
64
- end
65
- end
124
+ # we don't care about any other column (and, therefore,
125
+ # we are done with our declarations)
126
+ ```
66
127
 
67
- # fourth column is called age
68
- # we make it into an integer
69
- # age should be greater than 0
70
- i.column :age do
71
- process do |r|
72
- r.to_i
73
- end
128
+ Notice that `colref` can be a string (e.g., `'A'`) or an integer
129
+ (first column is one).
74
130
 
75
- check do |r|
76
- r > 0
77
- end
131
+ Notice also that if `process` and `check` are specified, then `check`
132
+ will receive the result of invoking `process` on the cell value. This
133
+ makes sense if process is used to make the cell value more accessible
134
+ to ruby code (e.g., transforming a string into an integer).
135
+
136
+ Finally we can specify how we process lines, using the `mapping`
137
+ directive. Mapping takes an arbitrary piece of ruby code, which can
138
+ reference the fields of a row.
139
+
140
+ For instance:
141
+
142
+ ```ruby
143
+ i.mapping do |row|
144
+ puts "#{row[:name][:value]} is #{row[:age][:value]} years old"
78
145
  end
146
+ ```
147
+
148
+ Notice that the data read from a line is stored in a hash which uses
149
+ the column names and stores names in the `:value` key.
150
+
151
+ Now we are all set and we can start working with the data.
152
+
153
+ First use `read` or `load` (synonyms), to read all data and put it
154
+ into a `@table` instance variable. This function uses the `column`
155
+ declarations to read data and executes the `process` and `check`
156
+ functions for each cell read.
157
+
158
+ ```ruby
159
+ i.read
160
+ ```
161
+
162
+ We can now use `errors` to see whether any of the `check` functions
163
+ failed:
79
164
 
80
- # when we decide to process the file, for every row
81
- # we print the value of the name and the value of the surname
82
- i.mapping do |r|
83
- puts "#{r[:name][:value]} #{r[:surname][:value]}"
165
+ ```ruby
166
+ array_of_strings = i.errors
167
+ array_of_strings ech do |error_line|
168
+ puts error_line
84
169
  end
170
+ ```
171
+
172
+ Now we can process the file with the `process` function, which
173
+ executes the `mapping` directive for each line read from the file.
85
174
 
86
- i.read "/home/adolfo/Desktop/a.ods"
175
+ ```ruby
87
176
  i.process
88
177
  ```
89
178
 
90
- ## Known Bugs and Limitations
179
+ If you need to perform more complex elaborations on the data, you can
180
+ also directly access all data read, using the `table` method, which
181
+ returns an array of hashes (see next section for the details).
182
+
183
+ ```ruby
184
+ i.table
185
+ ```
186
+
187
+ For further details and a couple of working examples, look in the
188
+ examples directory.
189
+
190
+
191
+ ## Digging deeper
192
+
193
+ The `read` method fills a `@table` instance variable with an array of
194
+ hashes. Each hash represents a line of the file.
195
+
196
+ Each hash contains one key per column, following your specification.
197
+ Its value is, in turn, a hash with the following structure:
198
+
199
+ ```ruby
200
+ {
201
+ value: ..., # the result of calling process on the cell
202
+ row_number: ... # the row number
203
+ col_number: ... # the column number
204
+ error: ... # the result of calling check on the cell processed value
205
+ }
206
+ ```
207
+
208
+ Thus, for instance, given the example above:
209
+
210
+ ```ruby
211
+ i.table
212
+ [ { name: { value: "John", row_number: 1, col_number: 1, errors: nil },
213
+ age: { value: 30, row_number: 1, col_number: 2, errors: nil } },
214
+ { name: { value: "Jane", row_number: 2, col_number: 1, errors: nil },
215
+ age: { value: 31, row_number: 2, col_number: 2, errors: nil } } ]
216
+ ```
217
+
218
+ ## Simplifying the data read
219
+
220
+ The `Dreader::Util` class provides some functions to simplify and
221
+ restructure the hashes built by `dreader`.
222
+
223
+ More in details:
224
+
225
+ `Dreader::Util.simplify hash` simplifies the hash passed as input by
226
+ removing all information but the value and making the value
227
+ accessible directly from the name of the column.
228
+
229
+ ```ruby
230
+ Dreader::Util.simplify i.table[0]
231
+ {name: "John", age: 30}
232
+ ```
233
+
234
+ `Dreader::Util.slice hash, keys` and `Dreader::Util.slice hash,
235
+ keys`, where `keys` is an arrays of keys, are respectively used to
236
+ select or remove some keys from `hash`.
237
+
238
+ ```ruby
239
+ Dreader::Util.slice i.table[0], [:age]
240
+ {age: 30}
241
+
242
+ Dreader::Util.clean i.table[0], [:age]
243
+ {name: "John"}
244
+ ```
245
+
246
+ Finally, the `Dreader::Util.restructure` method helps building hashes
247
+ to create
248
+ [ActiveModel](http://api.rubyonrails.org/classes/ActiveModel/Model.html)
249
+ objects with nested attributes:
250
+
251
+ ```ruby
252
+ hash = {name: "John", surname: "Doe", address: "Unknown", city: "NY" }
253
+
254
+ Dreader::Util.restructure hash, [:name, :surname], :address_attributes, [:address, :city]
255
+ {name: "John", surname: "Doe", address_attributes: {address: "Unknonw", city: "NY"}}
256
+ ```
257
+
258
+
259
+ ## Debugging your specification
260
+
261
+ If you are not sure about what is going on (like I often am when
262
+ reading tabular data), you can use the `debug` function, which prints
263
+ the current configuration, reads some records from your files, and
264
+ shows them to standard output:
265
+
266
+
267
+ ```ruby
268
+ i.debug
269
+ i.debug 40 # read 40 lines (from first_row, if the option is declared)
270
+ i.debug 40, filename # like above, but read from filename
271
+ ```
272
+
273
+ Another possibility is getting the value of the `@table` variable,
274
+ which contains all the data read.
275
+
276
+ ## Known Limitations
277
+
278
+ At the moment:
279
+
280
+ - it is not possible to specify column references using header names
281
+ (like Roo does).
282
+ - it is not possible to pass options to the file readers. As a
283
+ consequence tab-separated files must have the `.tsv` extension to be
284
+ correctly parsed.
285
+ - some testing wouldn't hurt.
286
+
287
+ ## Known Bugs
91
288
 
92
289
  No known bugs and an unknown number of unknown bugs.
93
290
 
@@ -0,0 +1,48 @@
1
+ # simple example which shows processing data from LibreOffice spreadsheets
2
+
3
+ require 'dreader'
4
+
5
+ processor = Dreader::Engine.new
6
+
7
+ processor.options do
8
+ first_row 2
9
+ filename "cities_by_state.ods"
10
+ end
11
+
12
+ processor.column :state do |col|
13
+ col.colref 'A'
14
+ end
15
+
16
+ processor.column :cities do |col|
17
+ col.colref 'B'
18
+ col.check do |data|
19
+ data.class == Integer
20
+ end
21
+ end
22
+
23
+ processor.mapping do |row|
24
+ hash = Dreader::Util.simplify row
25
+ puts " states: #{hash[:state]} number of cities: #{hash[:cities]}"
26
+ end
27
+
28
+ printf "Loading the spreadsheet..."
29
+ processor.load
30
+ puts "done!"
31
+
32
+ puts "Checking errors..."
33
+ errors = processor.errors
34
+ if errors.size > 0
35
+ puts " Errors found:"
36
+ processor.errors.each do |error|
37
+ puts error
38
+ end
39
+ else
40
+ puts " No errors found."
41
+ end
42
+ puts "done!"
43
+
44
+ puts "Processing the spreadsheet..."
45
+ processor.process
46
+ puts "... done"
47
+
48
+
@@ -0,0 +1,84 @@
1
+ require 'dreader'
2
+
3
+ # this is the class which will contain all the data we read from the file
4
+ class City
5
+ [:city, :state, :population, :lat, :lon].each do |var|
6
+ attr_accessor var
7
+ end
8
+
9
+ def initialize(hash)
10
+ hash.each do |k, v|
11
+ self.send("#{k}=", v)
12
+ end
13
+ end
14
+ end
15
+
16
+ importer = Dreader::Engine.new
17
+
18
+ # read from us_cities.tsv, lines from 2 to 10 (included)
19
+ importer.options do
20
+ filename "us_cities.tsv"
21
+ first_row 2
22
+ last_row 10
23
+ end
24
+
25
+ # these are the columns for which we only need to specify column and name
26
+ [[:city, 2], [:state, 3], [:latlon, 11]].each do |val|
27
+ # val[0] -> :city
28
+ # val[1] -> 2
29
+ importer.column val[0] do |col|
30
+ col.colref val[1]
31
+ col.process do |val|
32
+ val.strip
33
+ end
34
+ end
35
+ end
36
+
37
+ # the population column requires more work
38
+ importer.column :population do |col|
39
+ col.colref 4
40
+
41
+ # make "3,000" into 3000 (int)
42
+ col.process do |value|
43
+ value.gsub(",", "").to_i
44
+ end
45
+
46
+ end
47
+
48
+ cities = []
49
+
50
+ importer.mapping do |row|
51
+ # remove all additional information stored in each cell
52
+ r = Dreader::Util.simplify row
53
+
54
+ # make latlon into the lat, lon fields
55
+ r[:lat], r[:lon] = r[:latlon].split(" ")
56
+
57
+ # now r contains something like
58
+ # {lat: ..., lon: ..., city: ..., state: ..., population: ..., latlon: ...}
59
+
60
+ # remove fields which are not understood by the Cities class and
61
+ # make a new instance
62
+ cleaned = Dreader::Util.clean r, [:latlon]
63
+
64
+ # you must declare an array cities before calling importer.process
65
+ cities << City.new(cleaned)
66
+ end
67
+
68
+ # print to stdout what we told dreader to read
69
+ # (useful only for ... debugging!)
70
+ importer.debug 10
71
+
72
+ # load and process
73
+ importer.load
74
+ cities = []
75
+ importer.process
76
+
77
+ # output everything to see whether it works
78
+ puts "First ten cities in the US (source Wikipedia)"
79
+ cities.each do |city|
80
+ [:city, :state, :population, :lat, :lon].each do |var|
81
+ puts "#{var.to_s.capitalize}: #{city.send(var)}"
82
+ end
83
+ puts ""
84
+ end
@@ -0,0 +1,308 @@
1
+ 2016 rank City State[5] 2016 estimate 2010 Census Change 2016 land area 2016 land area 2016 pop density 2016 pop density Location
2
+ 1 New York[6] New York 8537673 8175133 +4.43% 301.5 sq mi 780.9 km2 28,317/sq mi 10,933/km2 40.6635°N 73.9387°W
3
+ 2 Los Angeles California 3976322 3792621 +4.84% 468.7 sq mi 1,213.9 km2 8,484/sq mi 3,276/km2 34.0194°N 118.4108°W
4
+ 3 Chicago Illinois 2704958 2695598 +0.35% 227.3 sq mi 588.7 km2 11,900/sq mi 4,600/km2 41.8376°N 87.6818°W
5
+ 4 Houston[7] Texas 2303482 2100263 +9.68% 637.5 sq mi 1,651.1 km2 3,613/sq mi 1,395/km2 29.7866°N 95.3909°W
6
+ 5 Phoenix Arizona 1615017 1445632 +11.72% 517.6 sq mi 1,340.6 km2 3,120/sq mi 1,200/km2 33.5722°N 112.0901°W
7
+ 6 Philadelphia[8] Pennsylvania 1567872 1526006 +2.74% 134.2 sq mi 347.6 km2 11,683/sq mi 4,511/km2 40.0094°N 75.1333°W
8
+ 7 San Antonio Texas 1492510 1327407 +12.44% 461.0 sq mi 1,194.0 km2 3,238/sq mi 1,250/km2 29.4724°N 98.5251°W
9
+ 8 San Diego California 1406630 1307402 +7.59% 325.2 sq mi 842.3 km2 4,325/sq mi 1,670/km2 32.8153°N 117.1350°W
10
+ 9 Dallas Texas 1317929 1197816 +10.03% 340.9 sq mi 882.9 km2 3,866/sq mi 1,493/km2 32.7933°N 96.7665°W
11
+ 10 San Jose California 1025350 945942 +8.39% 177.5 sq mi 459.7 km2 5,777/sq mi 2,231/km2 37.2967°N 121.8189°W
12
+ 11 Austin Texas 947890 790390 +19.93% 312.7 sq mi 809.9 km2 3,031/sq mi 1,170/km2 30.3039°N 97.7544°W
13
+ 12 Jacksonville[9] Florida 880619 821784 +7.16% 747.4 sq mi 1,935.8 km2 1,178/sq mi 455/km2 30.3369°N 81.6616°W
14
+ 13 San Francisco[10] California 870887 805235 +8.15% 46.9 sq mi 121.5 km2 18,569/sq mi 7,170/km2 37.7272°N 123.0322°W
15
+ 14 Columbus Ohio 860090 787033 +9.28% 218.5 sq mi 565.9 km2 3,936/sq mi 1,520/km2 39.9852°N 82.9848°W
16
+ 15 Indianapolis[11] Indiana 855164 820445 +4.23% 361.5 sq mi 936.3 km2 2,366/sq mi 914/km2 39.7767°N 86.1459°W
17
+ 16 Fort Worth Texas 854113 741206 +15.23% 342.9 sq mi 888.1 km2 2,491/sq mi 962/km2 32.7815°N 97.3467°W
18
+ 17 Charlotte North Carolina 842051 731424 +15.12% 305.4 sq mi 791.0 km2 2,757/sq mi 1,064/km2 35.2078°N 80.8310°W
19
+ 18 Seattle Washington 704352 608660 +15.72% 83.8 sq mi 217.0 km2 8,405/sq mi 3,245/km2 47.6205°N 122.3509°W
20
+ 19 Denver[12] Colorado 693060 600158 +15.48% 153.3 sq mi 397.0 km2 4,521/sq mi 1,746/km2 39.7619°N 104.8811°W
21
+ 20 El Paso Texas 683080 649121 +5.23% 256.8 sq mi 665.1 km2 2,660/sq mi 1,030/km2 31.8484°N 106.4270°W
22
+ 21 Washington[13] District of Columbia 681170 601723 +13.20% 61.1 sq mi 158.2 km2 11,148/sq mi 4,304/km2 38.9041°N 77.0172°W
23
+ 22 Boston Massachusetts 673184 617594 +9.00% 48.3 sq mi 125.1 km2 13,938/sq mi 5,381/km2 42.3320°N 71.0202°W
24
+ 23 Detroit Michigan 672795 713777 −5.74% 138.8 sq mi 359.5 km2 4,847/sq mi 1,871/km2 42.3830°N 83.1022°W
25
+ 24 Nashville[14] Tennessee 660388 601222 +9.84% 475.9 sq mi 1,232.6 km2 1,388/sq mi 536/km2 36.1718°N 86.7850°W
26
+ 25 Memphis Tennessee 652717 646889 +0.90% 317.4 sq mi 822.1 km2 2,056/sq mi 794/km2 35.1028°N 89.9774°W
27
+ 26 Portland Oregon 639863 583776 +9.61% 133.5 sq mi 345.8 km2 4,793/sq mi 1,851/km2 45.5370°N 122.6500°W
28
+ 27 Oklahoma City Oklahoma 638367 579999 +10.06% 606.3 sq mi 1,570.3 km2 1,053/sq mi 407/km2 35.4671°N 97.5137°W
29
+ 28 Las Vegas Nevada 632912 583756 +8.42% 134.4 sq mi 348.1 km2 4,709/sq mi 1,818/km2 36.2292°N 115.2601°W
30
+ 29 Louisville[15] Kentucky 616261 597337 +3.17% 263.5 sq mi 682.5 km2 2,339/sq mi 903/km2 38.1654°N 85.6474°W
31
+ 30 Baltimore[16] Maryland 614664 620961 −1.01% 80.9 sq mi 209.5 km2 7,598/sq mi 2,934/km2 39.3000°N 76.6105°W
32
+ 31 Milwaukee Wisconsin 595047 594833 +0.04% 96.2 sq mi 249.2 km2 6,186/sq mi 2,388/km2 43.0633°N 87.9667°W
33
+ 32 Albuquerque New Mexico 559277 545852 +2.46% 188.2 sq mi 487.4 km2 2,972/sq mi 1,147/km2 35.1056°N 106.6474°W
34
+ 33 Tucson Arizona 530706 520116 +2.04% 230.8 sq mi 597.8 km2 2,299/sq mi 888/km2 32.1531°N 110.8706°W
35
+ 34 Fresno California 522053 494665 +5.54% 114.4 sq mi 296.3 km2 4,563/sq mi 1,762/km2 36.7836°N 119.7934°W
36
+ 35 Sacramento California 495234 466488 +6.16% 97.9 sq mi 253.6 km2 5,059/sq mi 1,953/km2 38.5666°N 121.4686°W
37
+ 36 Mesa Arizona 484587 439041 +10.37% 137.9 sq mi 357.2 km2 3,514/sq mi 1,357/km2 33.4019°N 111.7174°W
38
+ 37 Kansas City Missouri 481420 459787 +4.71% 315.0 sq mi 815.8 km2 1,528/sq mi 590/km2 39.1251°N 94.5510°W
39
+ 38 Atlanta Georgia 472522 420003 +12.50% 133.5 sq mi 345.8 km2 3,539/sq mi 1,366/km2 33.7629°N 84.4227°W
40
+ 39 Long Beach California 470130 462257 +1.70% 50.3 sq mi 130.3 km2 9,347/sq mi 3,609/km2 33.8092°N 118.1553°W
41
+ 40 Colorado Springs Colorado 465101 416427 +11.69% 195.6 sq mi 506.6 km2 2,378/sq mi 918/km2 38.8673°N 104.7607°W
42
+ 41 Raleigh North Carolina 458880 403892 +13.61% 145.1 sq mi 375.8 km2 3,163/sq mi 1,221/km2 35.8306°N 78.6418°W
43
+ 42 Miami Florida 453579 399457 +13.55% 36.0 sq mi 93.2 km2 12,599/sq mi 4,865/km2 25.7752°N 80.2086°W
44
+ 43 Virginia Beach[16] Virginia 452602 437994 +3.34% 244.7 sq mi 633.8 km2 1,850/sq mi 710/km2 36.7800°N 76.0252°W
45
+ 44 Omaha Nebraska 446970 408958 +9.29% 133.2 sq mi 345.0 km2 3,356/sq mi 1,296/km2 41.2644°N 96.0451°W
46
+ 45 Oakland California 420005 390724 +7.49% 55.9 sq mi 144.8 km2 7,514/sq mi 2,901/km2 37.7698°N 122.2257°W
47
+ 46 Minneapolis Minnesota 413651 382578 +8.12% 54.0 sq mi 139.9 km2 7,660/sq mi 2,960/km2 44.9633°N 93.2683°W
48
+ 47 Tulsa Oklahoma 403090 391906 +2.85% 196.8 sq mi 509.7 km2 2,048/sq mi 791/km2 36.1279°N 95.9023°W
49
+ 48 Arlington Texas 392772 365438 +7.48% 95.8 sq mi 248.1 km2 4,100/sq mi 1,600/km2 32.7007°N 97.1247°W
50
+ 49 New Orleans[17] Louisiana 391495 343829 +13.86% 169.4 sq mi 438.7 km2 2,311/sq mi 892/km2 30.0534°N 89.9345°W
51
+ 50 Wichita Kansas 389902 382368 +1.97% 160.4 sq mi 415.4 km2 2,431/sq mi 939/km2 37.6907°N 97.3459°W
52
+ 51 Cleveland Ohio 385809 396815 −2.77% 77.7 sq mi 201.2 km2 4,965/sq mi 1,917/km2 41.4785°N 81.6794°W
53
+ 52 Tampa Florida 377165 335709 +12.35% 113.4 sq mi 293.7 km2 3,326/sq mi 1,284/km2 27.9701°N 82.4797°W
54
+ 53 Bakersfield California 376380 347483 +8.32% 148.8 sq mi 385.4 km2 2,529/sq mi 976/km2 35.3212°N 119.0183°W
55
+ 54 Aurora Colorado 361710 325078 +11.27% 153.5 sq mi 397.6 km2 2,356/sq mi 910/km2 39.6880°N 104.6897°W
56
+ 55 Honolulu[2] Hawaii 351792 337256 +4.31% 60.5 sq mi 156.7 km2 5,815/sq mi 2,245/km2 21.3243°N 157.8476°W
57
+ 56 Anaheim California 351043 336265 +4.39% 50.0 sq mi 129.5 km2 7,021/sq mi 2,711/km2 33.8555°N 117.7601°W
58
+ 57 Santa Ana California 334217 324528 +2.99% 27.1 sq mi 70.2 km2 12,333/sq mi 4,762/km2 33.7363°N 117.8830°W
59
+ 58 Corpus Christi Texas 325733 305215 +6.72% 174.6 sq mi 452.2 km2 1,866/sq mi 720/km2 27.7543°N 97.1734°W
60
+ 59 Riverside California 324722 303871 +6.86% 81.2 sq mi 210.3 km2 3,999/sq mi 1,544/km2 33.9381°N 117.3932°W
61
+ 60 Lexington[18] Kentucky 318449 295803 +7.66% 283.6 sq mi 734.5 km2 1,123/sq mi 434/km2 38.0407°N 84.4583°W
62
+ 61 St. Louis[16] Missouri 311404 319294 −2.47% 62.0 sq mi 160.6 km2 5,023/sq mi 1,939/km2 38.6357°N 90.2446°W
63
+ 62 Stockton California 307072 291707 +5.27% 61.7 sq mi 159.8 km2 4,977/sq mi 1,922/km2 37.9763°N 121.3133°W
64
+ 63 Pittsburgh Pennsylvania 303625 305704 −0.68% 55.4 sq mi 143.5 km2 5,481/sq mi 2,116/km2 40.4398°N 79.9766°W
65
+ 64 Saint Paul Minnesota 302398 285068 +6.08% 52.0 sq mi 134.7 km2 5,815/sq mi 2,245/km2 44.9489°N 93.1041°W
66
+ 65 Cincinnati Ohio 298800 296943 +0.63% 77.4 sq mi 200.5 km2 3,860/sq mi 1,490/km2 39.1402°N 84.5058°W
67
+ 66 Anchorage[19] Alaska 298192 291826 +2.18% 1,706.6 sq mi 4,420.1 km2 175/sq mi 68/km2 61.1743°N 149.2843°W
68
+ 67 Henderson Nevada 292969 257729 +13.67% 104.7 sq mi 271.2 km2 2,798/sq mi 1,080/km2 36.0097°N 115.0357°W
69
+ 68 Greensboro North Carolina 287027 269666 +6.44% 128.3 sq mi 332.3 km2 2,237/sq mi 864/km2 36.0951°N 79.8270°W
70
+ 69 Plano Texas 286057 259841 +10.09% 71.7 sq mi 185.7 km2 3,990/sq mi 1,540/km2 33.0508°N 96.7479°W
71
+ 70 Newark New Jersey 281764 277140 +1.67% 24.1 sq mi 62.4 km2 11,691/sq mi 4,514/km2 40.7242°N 74.1726°W
72
+ 71 Lincoln Nebraska 280364 258379 +8.51% 92.1 sq mi 238.5 km2 3,044/sq mi 1,175/km2 40.8105°N 96.6803°W
73
+ 72 Toledo Ohio 278508 287208 −3.03% 80.7 sq mi 209.0 km2 3,451/sq mi 1,332/km2 41.6641°N 83.5819°W
74
+ 73 Orlando Florida 277173 238300 +16.31% 105.2 sq mi 272.5 km2 2,635/sq mi 1,017/km2 28.4166°N 81.2736°W
75
+ 74 Chula Vista California 267172 243916 +9.53% 49.6 sq mi 128.5 km2 5,387/sq mi 2,080/km2 32.6277°N 117.0152°W
76
+ 75 Irvine California 266122 212375 +25.31% 65.6 sq mi 169.9 km2 4,057/sq mi 1,566/km2 33.6784°N 117.7713°W
77
+ 76 Fort Wayne Indiana 264488 253691 +4.26% 110.6 sq mi 286.5 km2 2,391/sq mi 923/km2 41.0882°N 85.1439°W
78
+ 77 Jersey City New Jersey 264152 247597 +6.69% 14.8 sq mi 38.3 km2 17,848/sq mi 6,891/km2 40.7114°N 74.0648°W
79
+ 78 Durham North Carolina 263016 228330 +15.19% 109.8 sq mi 284.4 km2 2,395/sq mi 925/km2 35.9811°N 78.9029°W
80
+ 79 St. Petersburg Florida 260999 244769 +6.63% 61.8 sq mi 160.1 km2 4,223/sq mi 1,631/km2 27.7620°N 82.6441°W
81
+ 80 Laredo Texas 257156 236091 +8.92% 101.1 sq mi 261.8 km2 2,544/sq mi 982/km2 27.5604°N 99.4892°W
82
+ 81 Buffalo New York 256902 261310 −1.69% 40.4 sq mi 104.6 km2 6,359/sq mi 2,455/km2 42.8925°N 78.8597°W
83
+ 82 Madison Wisconsin 252551 233209 +8.29% 77.0 sq mi 199.4 km2 3,280/sq mi 1,270/km2 43.0878°N 89.4299°W
84
+ 83 Lubbock Texas 252506 229573 +9.99% 124.6 sq mi 322.7 km2 2,027/sq mi 783/km2 33.5656°N 101.8867°W
85
+ 84 Chandler Arizona 247477 236123 +4.81% 64.9 sq mi 168.1 km2 3,813/sq mi 1,472/km2 33.2829°N 111.8549°W
86
+ 85 Scottsdale Arizona 246645 217385 +13.46% 183.9 sq mi 476.3 km2 1,341/sq mi 518/km2 33.6843°N 111.8611°W
87
+ 86 Glendale Arizona 245895 226721 +8.46% 59.1 sq mi 153.1 km2 4,161/sq mi 1,607/km2 33.5331°N 112.1899°W
88
+ 87 Reno Nevada 245255 225221 +8.90% 107.3 sq mi 277.9 km2 2,286/sq mi 883/km2 39.5491°N 119.8499°W
89
+ 88 Norfolk[16] Virginia 245115 242803 +0.95% 53.3 sq mi 138.0 km2 4,599/sq mi 1,776/km2 36.9230°N 76.2446°W
90
+ 89 Winston–Salem North Carolina 242203 229617 +5.48% 132.5 sq mi 343.2 km2 1,828/sq mi 706/km2 36.1027°N 80.2610°W
91
+ 90 North Las Vegas Nevada 238702 216961 +10.02% 98.0 sq mi 253.8 km2 2,436/sq mi 941/km2 36.2857°N 115.0939°W
92
+ 91 Irving Texas 238289 216290 +10.17% 67.0 sq mi 173.5 km2 3,557/sq mi 1,373/km2 32.8577°N 96.9700°W
93
+ 92 Chesapeake[16] Virginia 237940 222209 +7.08% 338.5 sq mi 876.7 km2 703/sq mi 271/km2 36.6794°N 76.3018°W
94
+ 93 Gilbert[20] Arizona 237133 208453 +13.76% 68.0 sq mi 176.1 km2 3,487/sq mi 1,346/km2 33.3103°N 111.7431°W
95
+ 94 Hialeah Florida 236387 224669 +5.22% 21.5 sq mi 55.7 km2 10,995/sq mi 4,245/km2 25.8699°N 80.3029°W
96
+ 95 Garland Texas 234943 226876 +3.56% 57.0 sq mi 147.6 km2 4,122/sq mi 1,592/km2 32.9098°N 96.6303°W
97
+ 96 Fremont California 233136 214089 +8.90% 77.5 sq mi 200.7 km2 3,008/sq mi 1,161/km2 37.4945°N 121.9412°W
98
+ 97 Baton Rouge[21] Louisiana 227715 229493 −0.77% 85.9 sq mi 222.5 km2 2,651/sq mi 1,024/km2 30.4422°N 91.1309°W
99
+ 98 Richmond[16] Virginia 223170 204214 +9.28% 59.8 sq mi 154.9 km2 3,732/sq mi 1,441/km2 37.5314°N 77.4760°W
100
+ 99 Boise[22] Idaho 223154 205671 +8.50% 82.1 sq mi 212.6 km2 2,718/sq mi 1,049/km2 43.6002°N 116.2317°W
101
+ 100 San Bernardino California 216239 209924 +3.01% 61.5 sq mi 159.3 km2 3,516/sq mi 1,358/km2 34.1416°N 117.2936°W
102
+ 101 Spokane Washington 215973 208916 +3.38% 68.7 sq mi 177.9 km2 3,144/sq mi 1,214/km2 47.6669°N 117.4333°W
103
+ 102 Des Moines Iowa 215472 203433 +5.92% 88.9 sq mi 230.2 km2 2,424/sq mi 936/km2 41.5726°N 93.6102°W
104
+ 103 Modesto California 212175 201165 +5.47% 43.0 sq mi 111.4 km2 4,934/sq mi 1,905/km2 37.6375°N 121.0030°W
105
+ 104 Birmingham Alabama 212157 212237 −0.04% 146.1 sq mi 378.4 km2 1,452/sq mi 561/km2 33.5274°N 86.7990°W
106
+ 105 Tacoma Washington 211277 198397 +6.49% 49.7 sq mi 128.7 km2 4,251/sq mi 1,641/km2 47.2522°N 122.4598°W
107
+ 106 Fontana California 209665 196069 +6.93% 43.0 sq mi 111.4 km2 4,876/sq mi 1,883/km2 34.1090°N 117.4629°W
108
+ 107 Rochester New York 208880 210565 −0.80% 35.8 sq mi 92.7 km2 5,835/sq mi 2,253/km2 43.1699°N 77.6169°W
109
+ 108 Oxnard California 207906 197899 +5.06% 26.9 sq mi 69.7 km2 7,729/sq mi 2,984/km2 34.2023°N 119.2046°W
110
+ 109 Moreno Valley California 205499 193365 +6.28% 51.3 sq mi 132.9 km2 4,006/sq mi 1,547/km2 33.9233°N 117.2057°W
111
+ 110 Fayetteville North Carolina 204759 200564 +2.09% 147.7 sq mi 382.5 km2 1,386/sq mi 535/km2 35.0828°N 78.9735°W
112
+ 111 Aurora Illinois 201110 197899 +1.62% 44.9 sq mi 116.3 km2 4,479/sq mi 1,729/km2 41.7635°N 88.2901°W
113
+ 112 Glendale California 200831 191719 +4.75% 30.4 sq mi 78.7 km2 6,606/sq mi 2,551/km2 34.1814°N 118.2458°W
114
+ 113 Yonkers New York 200807 195976 +2.47% 18.0 sq mi 46.6 km2 11,156/sq mi 4,307/km2 40.9459°N 73.8674°W
115
+ 114 Huntington Beach California 200652 189992 +5.61% 26.9 sq mi 69.7 km2 7,459/sq mi 2,880/km2 33.6906°N 118.0093°W
116
+ 115 Montgomery Alabama 200022 205764 −2.79% 159.8 sq mi 413.9 km2 1,252/sq mi 483/km2 32.3472°N 86.2661°W
117
+ 116 Amarillo Texas 199582 190695 +4.66% 101.4 sq mi 262.6 km2 1,968/sq mi 760/km2 35.1999°N 101.8302°W
118
+ 117 Little Rock Arkansas 198541 193524 +2.59% 118.7 sq mi 307.4 km2 1,673/sq mi 646/km2 34.7254°N 92.3586°W
119
+ 118 Akron Ohio 197633 199110 −0.74% 62.0 sq mi 160.6 km2 3,188/sq mi 1,231/km2 41.0805°N 81.5214°W
120
+ 119 Columbus[23] Georgia 197485 189885 +4.00% 216.4 sq mi 560.5 km2 913/sq mi 353/km2 32.5102°N 84.8749°W
121
+ 120 Augusta[24] Georgia 197081 195844 +0.63% 302.5 sq mi 783.5 km2 652/sq mi 252/km2 33.3655°N 82.0734°W
122
+ 121 Grand Rapids Michigan 196445 188040 +4.47% 44.4 sq mi 115.0 km2 4,424/sq mi 1,708/km2 42.9612°N 85.6556°W
123
+ 122 Shreveport Louisiana 194920 199311 −2.20% 107.1 sq mi 277.4 km2 1,820/sq mi 700/km2 32.4669°N 93.7922°W
124
+ 123 Salt Lake City Utah 193744 186440 +3.92% 111.2 sq mi 288.0 km2 1,742/sq mi 673/km2 40.7769°N 111.9310°W
125
+ 124 Huntsville Alabama 193079 180105 +7.20% 213.4 sq mi 552.7 km2 905/sq mi 349/km2 34.6990°N 86.6730°W
126
+ 125 Mobile Alabama 192904 195111 −1.13% 139.4 sq mi 361.0 km2 1,384/sq mi 534/km2 30.6684°N 88.1002°W
127
+ 126 Tallahassee Florida 190894 181376 +5.25% 100.4 sq mi 260.0 km2 1,901/sq mi 734/km2 30.4551°N 84.2534°W
128
+ 127 Grand Prairie Texas 190682 175396 +8.72% 72.3 sq mi 187.3 km2 2,637/sq mi 1,018/km2 32.6869°N 97.0211°W
129
+ 128 Overland Park Kansas 188966 173372 +8.99% 75.1 sq mi 194.5 km2 2,516/sq mi 971/km2 38.8890°N 94.6906°W
130
+ 129 Knoxville Tennessee 186239 178874 +4.12% 98.5 sq mi 255.1 km2 1,891/sq mi 730/km2 35.9707°N 83.9493°W
131
+ 130 Port St. Lucie Florida 185132 164603 +12.47% 118.9 sq mi 307.9 km2 1,557/sq mi 601/km2 27.2806°N 80.3883°W
132
+ 131 Worcester Massachusetts 184508 181045 +1.91% 37.4 sq mi 96.9 km2 4,933/sq mi 1,905/km2 42.2695°N 71.8078°W
133
+ 132 Brownsville Texas 183823 175023 +5.03% 132.5 sq mi 343.2 km2 1,387/sq mi 536/km2 25.9991°N 97.4550°W
134
+ 133 Tempe Arizona 182498 161719 +12.85% 40.0 sq mi 103.6 km2 4,562/sq mi 1,761/km2 33.3884°N 111.9318°W
135
+ 134 Santa Clarita California 181972 176320 +3.21% 52.8 sq mi 136.8 km2 3,446/sq mi 1,331/km2 34.4030°N 118.5042°W
136
+ 135 Newport News[16] Virginia 181825 180719 +0.61% 69.1 sq mi 179.0 km2 2,631/sq mi 1,016/km2 37.0762°N 76.5220°W
137
+ 136 Cape Coral Florida 179804 154305 +16.53% 105.6 sq mi 273.5 km2 1,703/sq mi 658/km2 26.6432°N 81.9974°W
138
+ 137 Providence Rhode Island 179219 178042 +0.66% 18.4 sq mi 47.7 km2 9,740/sq mi 3,760/km2 41.8231°N 71.4188°W
139
+ 138 Fort Lauderdale Florida 178752 165521 +7.99% 34.6 sq mi 89.6 km2 5,166/sq mi 1,995/km2 26.1412°N 80.1467°W
140
+ 139 Chattanooga Tennessee 177571 167674 +5.90% 143.1 sq mi 370.6 km2 1,241/sq mi 479/km2 35.0660°N 85.2484°W
141
+ 140 Rancho Cucamonga California 176534 165269 +6.82% 40.0 sq mi 103.6 km2 4,413/sq mi 1,704/km2 34.1233°N 117.5642°W
142
+ 141 Oceanside California 175464 167086 +5.01% 41.3 sq mi 107.0 km2 4,249/sq mi 1,641/km2 33.2245°N 117.3062°W
143
+ 142 Santa Rosa California 175155 167815 +4.37% 41.3 sq mi 107.0 km2 4,241/sq mi 1,637/km2 38.4468°N 122.7061°W
144
+ 143 Garden Grove California 174858 170883 +2.33% 18.0 sq mi 46.6 km2 9,714/sq mi 3,751/km2 33.7788°N 117.9605°W
145
+ 144 Vancouver Washington 174826 161791 +8.06% 46.9 sq mi 121.5 km2 3,728/sq mi 1,439/km2 45.6349°N 122.5957°W
146
+ 145 Sioux Falls South Dakota 174360 153888 +13.30% 75.4 sq mi 195.3 km2 2,312/sq mi 893/km2 43.5383°N 96.7320°W
147
+ 146 Ontario California 173212 163924 +5.67% 49.9 sq mi 129.2 km2 3,471/sq mi 1,340/km2 34.0394°N 117.6042°W
148
+ 147 McKinney Texas 172298 131117 +31.41% 63.0 sq mi 163.2 km2 2,735/sq mi 1,056/km2 33.1985°N 96.6680°W
149
+ 148 Elk Grove California 169743 153015 +10.93% 42.2 sq mi 109.3 km2 4,022/sq mi 1,553/km2 38.4146°N 121.3850°W
150
+ 149 Jackson Mississippi 169148 173514 −2.52% 111.0 sq mi 287.5 km2 1,524/sq mi 588/km2 32.3158°N 90.2128°W
151
+ 150 Pembroke Pines Florida 168587 154019 +9.46% 33.0 sq mi 85.5 km2 5,109/sq mi 1,973/km2 26.0210°N 80.3404°W
152
+ 151 Salem Oregon 167419 154637 +8.27% 48.6 sq mi 125.9 km2 3,445/sq mi 1,330/km2 44.9237°N 123.0232°W
153
+ 152 Springfield Missouri 167319 159498 +4.90% 82.3 sq mi 213.2 km2 2,033/sq mi 785/km2 37.1942°N 93.2913°W
154
+ 153 Corona California 166785 152374 +9.46% 39.5 sq mi 102.3 km2 4,222/sq mi 1,630/km2 33.8620°N 117.5655°W
155
+ 154 Eugene Oregon 166575 156185 +6.65% 44.1 sq mi 114.2 km2 3,777/sq mi 1,458/km2 44.0567°N 123.1162°W
156
+ 155 Fort Collins Colorado 164207 143986 +14.04% 55.8 sq mi 144.5 km2 2,943/sq mi 1,136/km2 40.5482°N 105.0648°W
157
+ 156 Peoria Arizona 164173 154065 +6.56% 175.7 sq mi 455.1 km2 934/sq mi 361/km2 33.7862°N 112.3080°W
158
+ 157 Frisco Texas 163656 116989 +39.89% 67.7 sq mi 175.3 km2 2,417/sq mi 933/km2 33.1554°N 96.8226°W
159
+ 158 Cary[25] North Carolina 162320 135234 +20.03% 56.5 sq mi 146.3 km2 2,873/sq mi 1,109/km2 35.7809°N 78.8133°W
160
+ 159 Lancaster California 160106 156633 +2.22% 94.3 sq mi 244.2 km2 1,698/sq mi 656/km2 34.6936°N 118.1753°W
161
+ 160 Hayward California 158937 144186 +10.23% 45.5 sq mi 117.8 km2 3,493/sq mi 1,349/km2 37.6287°N 122.1024°W
162
+ 161 Palmdale California 157356 152750 +3.02% 106.0 sq mi 274.5 km2 1,484/sq mi 573/km2 34.5910°N 118.1054°W
163
+ 162 Salinas California 157218 150441 +4.50% 23.6 sq mi 61.1 km2 6,662/sq mi 2,572/km2 36.6902°N 121.6337°W
164
+ 163 Alexandria[16] Virginia 155810 139966 +11.32% 15.0 sq mi 38.8 km2 10,387/sq mi 4,010/km2 38.8201°N 77.0841°W
165
+ 164 Lakewood Colorado 154393 142980 +7.98% 42.9 sq mi 111.1 km2 3,599/sq mi 1,390/km2 39.6989°N 105.1176°W
166
+ 165 Springfield Massachusetts 154074 153060 +0.66% 31.9 sq mi 82.6 km2 4,830/sq mi 1,860/km2 42.1155°N 72.5400°W
167
+ 166 Pasadena Texas 153351 149043 +2.89% 43.5 sq mi 112.7 km2 3,525/sq mi 1,361/km2 29.6586°N 95.1506°W
168
+ 167 Sunnyvale California 152771 140081 +9.06% 22.0 sq mi 57.0 km2 6,944/sq mi 2,681/km2 37.3858°N 122.0263°W
169
+ 168 Macon[26] Georgia 152555 91351 +67.00% 249.3 sq mi 645.7 km2 612/sq mi 236/km2 32.8088°N 83.6942°W
170
+ 169 Pomona California 152494 149058 +2.31% 23.0 sq mi 59.6 km2 6,630/sq mi 2,560/km2 34.0585°N 117.7611°W
171
+ 170 Hollywood Florida 151998 140768 +7.98% 27.3 sq mi 70.7 km2 5,568/sq mi 2,150/km2 26.0310°N 80.1646°W
172
+ 171 Kansas City[27] Kansas 151709 145786 +4.06% 124.8 sq mi 323.2 km2 1,216/sq mi 470/km2 39.1225°N 94.7418°W
173
+ 172 Escondido California 151613 143911 +5.35% 37.1 sq mi 96.1 km2 4,087/sq mi 1,578/km2 33.1331°N 117.0740°W
174
+ 173 Clarksville Tennessee 150287 132929 +13.06% 98.3 sq mi 254.6 km2 1,529/sq mi 590/km2 36.5664°N 87.3452°W
175
+ 174 Joliet Illinois 148262 147433 +0.56% 64.4 sq mi 166.8 km2 2,302/sq mi 889/km2 41.5177°N 88.1488°W
176
+ 175 Rockford Illinois 147651 152871 −3.41% 63.5 sq mi 164.5 km2 2,325/sq mi 898/km2 42.2588°N 89.0646°W
177
+ 176 Torrance California 147195 145438 +1.21% 20.5 sq mi 53.1 km2 7,180/sq mi 2,770/km2 33.8350°N 118.3414°W
178
+ 177 Naperville Illinois 147122 141853 +3.71% 38.7 sq mi 100.2 km2 3,802/sq mi 1,468/km2 41.7492°N 88.1620°W
179
+ 178 Paterson New Jersey 147000 146199 +0.55% 8.4 sq mi 21.8 km2 17,500/sq mi 6,800/km2 40.9148°N 74.1628°W
180
+ 179 Savannah Georgia 146763 136286 +7.69% 103.6 sq mi 268.3 km2 1,417/sq mi 547/km2 32.0025°N 81.1536°W
181
+ 180 Bridgeport Connecticut 145936 144229 +1.18% 16.1 sq mi 41.7 km2 9,064/sq mi 3,500/km2 41.1874°N 73.1958°W
182
+ 181 Mesquite Texas 143736 139824 +2.80% 47.2 sq mi 122.2 km2 3,045/sq mi 1,176/km2 32.7629°N 96.5888°W
183
+ 182 Killeen Texas 143400 127921 +12.10% 53.5 sq mi 138.6 km2 2,680/sq mi 1,030/km2 31.0777°N 97.7320°W
184
+ 183 Syracuse New York 143378 145170 −1.23% 25.0 sq mi 64.7 km2 5,735/sq mi 2,214/km2 43.0410°N 76.1436°W
185
+ 184 McAllen Texas 142212 129877 +9.50% 58.4 sq mi 151.3 km2 2,435/sq mi 940/km2 26.2322°N 98.2464°W
186
+ 185 Pasadena California 142059 137122 +3.60% 23.0 sq mi 59.6 km2 6,176/sq mi 2,385/km2 34.1606°N 118.1396°W
187
+ 186 Bellevue Washington 141400 122363 +15.56% 33.5 sq mi 86.8 km2 4,221/sq mi 1,630/km2 47.5979°N 122.1565°W
188
+ 187 Fullerton California 140721 135161 +4.11% 22.4 sq mi 58.0 km2 6,282/sq mi 2,425/km2 33.8857°N 117.9280°W
189
+ 188 Orange California 140504 136416 +3.00% 25.4 sq mi 65.8 km2 5,532/sq mi 2,136/km2 33.7870°N 117.8613°W
190
+ 189 Dayton Ohio 140489 141527 −0.73% 55.7 sq mi 144.3 km2 2,522/sq mi 974/km2 39.7774°N 84.1996°W
191
+ 190 Miramar Florida 138449 122041 +13.44% 29.4 sq mi 76.1 km2 4,709/sq mi 1,818/km2 25.9770°N 80.3358°W
192
+ 191 Thornton Colorado 136703 118772 +15.10% 35.7 sq mi 92.5 km2 3,829/sq mi 1,478/km2 39.9194°N 104.9428°W
193
+ 192 West Valley City Utah 136574 129480 +5.48% 35.5 sq mi 91.9 km2 3,847/sq mi 1,485/km2 40.6885°N 112.0118°W
194
+ 193 Olathe Kansas 135473 125872 +7.63% 60.9 sq mi 157.7 km2 2,225/sq mi 859/km2 38.8843°N 94.8195°W
195
+ 194 Hampton[16] Virginia 135410 137436 −1.47% 51.5 sq mi 133.4 km2 2,629/sq mi 1,015/km2 37.0480°N 76.2971°W
196
+ 195 Warren Michigan 135125 134056 +0.80% 34.4 sq mi 89.1 km2 3,928/sq mi 1,517/km2 42.4929°N 83.0250°W
197
+ 196 Midland Texas 134610 111147 +21.11% 74.4 sq mi 192.7 km2 1,809/sq mi 698/km2 32.0246°N 102.1135°W
198
+ 197 Waco Texas 134432 124805 +7.71% 89.0 sq mi 230.5 km2 1,510/sq mi 580/km2 31.5601°N 97.1860°W
199
+ 198 Charleston South Carolina 134385 120083 +11.91% 109.0 sq mi 282.3 km2 1,233/sq mi 476/km2 32.8179°N 79.9590°W
200
+ 199 Columbia South Carolina 134309 129272 +3.90% 133.5 sq mi 345.8 km2 1,006/sq mi 388/km2 34.0291°N 80.8980°W
201
+ 200 Denton Texas 133808 113383 +18.01% 93.4 sq mi 241.9 km2 1,433/sq mi 553/km2 33.2166°N 97.1414°W
202
+ 201 Carrollton Texas 133351 119097 +11.97% 36.3 sq mi 94.0 km2 3,674/sq mi 1,419/km2 32.9884°N 96.8998°W
203
+ 202 Surprise Arizona 132677 117517 +12.90% 107.9 sq mi 279.5 km2 1,230/sq mi 470/km2 33.6706°N 112.4527°W
204
+ 203 Roseville California 132671 118788 +11.69% 43.0 sq mi 111.4 km2 3,085/sq mi 1,191/km2 38.7690°N 121.3189°W
205
+ 204 Sterling Heights Michigan 132427 129699 +2.10% 36.5 sq mi 94.5 km2 3,628/sq mi 1,401/km2 42.5812°N 83.0303°W
206
+ 205 Murfreesboro Tennessee 131947 108755 +21.32% 55.9 sq mi 144.8 km2 2,360/sq mi 910/km2 35.8522°N 86.4160°W
207
+ 206 Gainesville Florida 131591 124354 +5.82% 62.3 sq mi 161.4 km2 2,112/sq mi 815/km2 29.6788°N 82.3461°W
208
+ 207 Cedar Rapids Iowa 131127 126326 +3.80% 70.8 sq mi 183.4 km2 1,852/sq mi 715/km2 41.9670°N 91.6778°W
209
+ 208 Visalia California 131074 124442 +5.33% 37.5 sq mi 97.1 km2 3,495/sq mi 1,349/km2 36.3273°N 119.3289°W
210
+ 209 Coral Springs Florida 130059 121096 +7.40% 23.8 sq mi 61.6 km2 5,465/sq mi 2,110/km2 26.2707°N 80.2593°W
211
+ 210 New Haven Connecticut 129934 129779 +0.12% 18.7 sq mi 48.4 km2 6,948/sq mi 2,683/km2 41.3108°N 72.9250°W
212
+ 211 Stamford Connecticut 129113 122643 +5.28% 37.6 sq mi 97.4 km2 3,434/sq mi 1,326/km2 41.0799°N 73.5460°W
213
+ 212 Thousand Oaks California 128888 126683 +1.74% 55.2 sq mi 143.0 km2 2,335/sq mi 902/km2 34.1933°N 118.8742°W
214
+ 213 Concord California 128726 122067 +5.46% 30.5 sq mi 79.0 km2 4,221/sq mi 1,630/km2 37.9722°N 122.0016°W
215
+ 214 Elizabeth New Jersey 128640 124969 +2.94% 12.3 sq mi 31.9 km2 10,459/sq mi 4,038/km2 40.6664°N 74.1935°W
216
+ 215 Lafayette[28] Louisiana 127626 120623 +5.81% 53.8 sq mi 139.3 km2 2,372/sq mi 916/km2 30.2074°N 92.0285°W
217
+ 216 Kent Washington 127514 92411 +37.99% 33.7 sq mi 87.3 km2 3,784/sq mi 1,461/km2 47.3880°N 122.2127°W
218
+ 217 Topeka Kansas 126808 127473 −0.52% 61.5 sq mi 159.3 km2 2,062/sq mi 796/km2 39.0347°N 95.6962°W
219
+ 218 Simi Valley California 126327 124237 +1.68% 41.5 sq mi 107.5 km2 3,044/sq mi 1,175/km2 34.2669°N 118.7485°W
220
+ 219 Santa Clara California 125948 116468 +8.14% 18.4 sq mi 47.7 km2 6,845/sq mi 2,643/km2 37.3646°N 121.9679°W
221
+ 220 Athens[29] Georgia 123371 115452 +6.86% 116.4 sq mi 301.5 km2 1,060/sq mi 410/km2 33.9496°N 83.3701°W
222
+ 221 Hartford Connecticut 123243 124775 −1.23% 17.4 sq mi 45.1 km2 7,083/sq mi 2,735/km2 41.7659°N 72.6816°W
223
+ 222 Victorville California 122265 115903 +5.49% 73.3 sq mi 189.8 km2 1,668/sq mi 644/km2 34.5277°N 117.3536°W
224
+ 223 Abilene Texas 122225 117063 +4.41% 106.7 sq mi 276.4 km2 1,146/sq mi 442/km2 32.4545°N 99.7381°W
225
+ 224 Norman Oklahoma 122180 110925 +10.15% 178.8 sq mi 463.1 km2 683/sq mi 264/km2 35.2406°N 97.3453°W
226
+ 225 Vallejo California 121299 115942 +4.62% 30.7 sq mi 79.5 km2 3,951/sq mi 1,525/km2 38.1079°N 122.2640°W
227
+ 226 Berkeley California 121240 112580 +7.69% 10.5 sq mi 27.2 km2 11,547/sq mi 4,458/km2 37.8670°N 122.2991°W
228
+ 227 Round Rock Texas 120892 99887 +21.03% 35.6 sq mi 92.2 km2 3,396/sq mi 1,311/km2 30.5252°N 97.6660°W
229
+ 228 Ann Arbor Michigan 120782 113934 +6.01% 28.1 sq mi 72.8 km2 4,298/sq mi 1,659/km2 42.2761°N 83.7309°W
230
+ 229 Fargo North Dakota 120762 105549 +14.41% 49.3 sq mi 127.7 km2 2,450/sq mi 950/km2 46.8652°N 96.8290°W
231
+ 230 Columbia Missouri 120612 108500 +11.16% 65.0 sq mi 168.3 km2 1,856/sq mi 717/km2 38.9473°N 92.3264°W
232
+ 231 Allentown Pennsylvania 120443 118032 +2.04% 17.5 sq mi 45.3 km2 6,882/sq mi 2,657/km2 40.5936°N 75.4784°W
233
+ 232 Evansville Indiana 119477 117429 +1.74% 47.3 sq mi 122.5 km2 2,526/sq mi 975/km2 37.9877°N 87.5347°W
234
+ 233 Beaumont Texas 118299 118296 0.00% 82.1 sq mi 212.6 km2 1,441/sq mi 556/km2 30.0849°N 94.1453°W
235
+ 234 Odessa Texas 117871 99940 +17.94% 45.2 sq mi 117.1 km2 2,608/sq mi 1,007/km2 31.8838°N 102.3411°W
236
+ 235 Wilmington North Carolina 117525 106476 +10.38% 51.6 sq mi 133.6 km2 2,278/sq mi 880/km2 34.2092°N 77.8858°W
237
+ 236 Arvada Colorado 117453 106433 +10.35% 38.6 sq mi 100.0 km2 3,043/sq mi 1,175/km2 39.8337°N 105.1503°W
238
+ 237 Independence Missouri 117030 116830 +0.17% 77.8 sq mi 201.5 km2 1,504/sq mi 581/km2 39.0855°N 94.3521°W
239
+ 238 Provo Utah 116868 112488 +3.89% 41.7 sq mi 108.0 km2 2,803/sq mi 1,082/km2 40.2453°N 111.6448°W
240
+ 239 Lansing Michigan 116020 114297 +1.51% 39.1 sq mi 101.3 km2 2,967/sq mi 1,146/km2 42.7143°N 84.5593°W
241
+ 240 El Monte California 115807 113475 +2.06% 9.6 sq mi 24.9 km2 12,063/sq mi 4,658/km2 34.0746°N 118.0291°W
242
+ 241 Springfield Illinois 115715 116250 −0.46% 60.1 sq mi 155.7 km2 1,925/sq mi 743/km2 39.7911°N 89.6446°W
243
+ 242 Fairfield California 114756 105321 +8.96% 40.9 sq mi 105.9 km2 2,806/sq mi 1,083/km2 38.2593°N 122.0321°W
244
+ 243 Clearwater Florida 114361 107685 +6.20% 25.9 sq mi 67.1 km2 4,415/sq mi 1,705/km2 27.9789°N 82.7666°W
245
+ 244 Peoria Illinois 114265 115007 −0.65% 48.2 sq mi 124.8 km2 2,371/sq mi 915/km2 40.7515°N 89.6174°W
246
+ 245 Rochester Minnesota 114011 106769 +6.78% 54.6 sq mi 141.4 km2 2,088/sq mi 806/km2 44.0154°N 92.4772°W
247
+ 246 Carlsbad California 113952 105328 +8.19% 37.7 sq mi 97.6 km2 3,023/sq mi 1,167/km2 33.1239°N 117.2828°W
248
+ 247 Westminster Colorado 113875 106114 +7.31% 31.7 sq mi 82.1 km2 3,592/sq mi 1,387/km2 39.8822°N 105.0644°W
249
+ 248 West Jordan Utah 113699 103712 +9.63% 32.3 sq mi 83.7 km2 3,520/sq mi 1,360/km2 40.6024°N 112.0008°W
250
+ 249 Pearland Texas 113570 91252 +24.46% 46.3 sq mi 119.9 km2 2,453/sq mi 947/km2 29.5558°N 95.3231°W
251
+ 250 Richardson Texas 113347 99223 +14.23% 28.6 sq mi 74.1 km2 3,963/sq mi 1,530/km2 32.9723°N 96.7081°W
252
+ 251 Downey California 113267 111772 +1.34% 12.4 sq mi 32.1 km2 9,134/sq mi 3,527/km2 33.9382°N 118.1309°W
253
+ 252 Miami Gardens Florida 113058 107167 +5.50% 18.2 sq mi 47.1 km2 6,212/sq mi 2,398/km2 25.9489°N 80.2436°W
254
+ 253 Temecula California 113054 100097 +12.94% 37.3 sq mi 96.6 km2 3,031/sq mi 1,170/km2 33.4931°N 117.1317°W
255
+ 254 Costa Mesa California 112822 109960 +2.60% 15.7 sq mi 40.7 km2 7,186/sq mi 2,775/km2 33.6659°N 117.9123°W
256
+ 255 College Station Texas 112141 93857 +19.48% 51.0 sq mi 132.1 km2 2,199/sq mi 849/km2 30.5852°N 96.2964°W
257
+ 256 Elgin Illinois 112123 108188 +3.64% 37.4 sq mi 96.9 km2 2,998/sq mi 1,158/km2 42.0396°N 88.3217°W
258
+ 257 Murrieta California 111674 103466 +7.93% 33.6 sq mi 87.0 km2 3,324/sq mi 1,283/km2 33.5721°N 117.1904°W
259
+ 258 Gresham Oregon 111523 105594 +5.61% 23.3 sq mi 60.3 km2 4,786/sq mi 1,848/km2 45.5023°N 122.4416°W
260
+ 259 High Point North Carolina 111223 104371 +6.57% 55.2 sq mi 143.0 km2 2,015/sq mi 778/km2 35.9900°N 79.9905°W
261
+ 260 Antioch California 110898 102372 +8.33% 29.4 sq mi 76.1 km2 3,772/sq mi 1,456/km2 37.9791°N 121.7962°W
262
+ 261 Inglewood California 110654 109673 +0.89% 9.1 sq mi 23.6 km2 12,160/sq mi 4,700/km2 33.9561°N 118.3443°W
263
+ 262 Cambridge Massachusetts 110651 105162 +5.22% 6.4 sq mi 16.6 km2 17,289/sq mi 6,675/km2 42.3760°N 71.1187°W
264
+ 263 Lowell Massachusetts 110558 106519 +3.79% 13.6 sq mi 35.2 km2 8,129/sq mi 3,139/km2 42.6390°N 71.3211°W
265
+ 264 Manchester New Hampshire 110506 109565 +0.86% 33.1 sq mi 85.7 km2 3,339/sq mi 1,289/km2 42.9849°N 71.4441°W
266
+ 265 Billings Montana 110323 104170 +5.91% 43.7 sq mi 113.2 km2 2,525/sq mi 975/km2 45.7885°N 108.5499°W
267
+ 266 Pueblo Colorado 110291 106595 +3.47% 53.6 sq mi 138.8 km2 2,058/sq mi 795/km2 38.2699°N 104.6123°W
268
+ 267 Palm Bay Florida 110104 103190 +6.70% 65.7 sq mi 170.2 km2 1,676/sq mi 647/km2 27.9856°N 80.6626°W
269
+ 268 Centennial Colorado 109932 100377 +9.52% 29.5 sq mi 76.4 km2 3,727/sq mi 1,439/km2 39.5906°N 104.8691°W
270
+ 269 Richmond California 109813 103701 +5.89% 30.1 sq mi 78.0 km2 3,648/sq mi 1,409/km2 37.9523°N 122.3606°W
271
+ 270 Ventura[30] California 109592 106433 +2.97% 21.8 sq mi 56.5 km2 5,027/sq mi 1,941/km2 34.2678°N 119.2542°W
272
+ 271 Pompano Beach Florida 109393 99845 +9.56% 24.0 sq mi 62.2 km2 4,558/sq mi 1,760/km2 26.2416°N 80.1339°W
273
+ 272 North Charleston South Carolina 109298 97471 +12.13% 73.7 sq mi 190.9 km2 1,483/sq mi 573/km2 32.9178°N 80.0650°W
274
+ 273 Everett Washington 109043 103019 +5.85% 33.3 sq mi 86.2 km2 3,275/sq mi 1,264/km2 47.9566°N 122.1914°W
275
+ 274 Waterbury Connecticut 108272 110366 −1.90% 28.5 sq mi 73.8 km2 3,799/sq mi 1,467/km2 41.5585°N 73.0367°W
276
+ 275 West Palm Beach Florida 108161 99919 +8.25% 55.1 sq mi 142.7 km2 1,963/sq mi 758/km2 26.7464°N 80.1251°W
277
+ 276 Boulder Colorado 108090 97385 +10.99% 24.8 sq mi 64.2 km2 4,358/sq mi 1,683/km2 40.0270°N 105.2519°W
278
+ 277 West Covina California 107847 106098 +1.65% 16.0 sq mi 41.4 km2 6,740/sq mi 2,600/km2 34.0559°N 117.9099°W
279
+ 278 Broken Arrow Oklahoma 107403 98850 +8.65% 61.7 sq mi 159.8 km2 1,741/sq mi 672/km2 36.0365°N 95.7810°W
280
+ 279 Clovis California 106583 95631 +11.45% 24.2 sq mi 62.7 km2 4,404/sq mi 1,700/km2 36.8282°N 119.6849°W
281
+ 280 Daly City California 106472 101123 +5.29% 7.6 sq mi 19.7 km2 14,009/sq mi 5,409/km2 37.7009°N 122.4650°W
282
+ 281 Lakeland Florida 106420 97422 +9.24% 65.9 sq mi 170.7 km2 1,615/sq mi 624/km2 28.0555°N 81.9549°W
283
+ 282 Santa Maria California 106290 99553 +6.77% 22.8 sq mi 59.1 km2 4,662/sq mi 1,800/km2 34.9332°N 120.4438°W
284
+ 283 Norwalk California 106178 105549 +0.60% 9.7 sq mi 25.1 km2 10,946/sq mi 4,226/km2 33.9076°N 118.0835°W
285
+ 284 Sandy Springs Georgia 105703 93853 +12.63% 37.7 sq mi 97.6 km2 2,804/sq mi 1,083/km2 33.9315°N 84.3687°W
286
+ 285 Hillsboro Oregon 105164 91611 +14.79% 25.0 sq mi 64.7 km2 4,207/sq mi 1,624/km2 45.5280°N 122.9357°W
287
+ 286 Green Bay Wisconsin 105139 104057 +1.04% 45.4 sq mi 117.6 km2 2,316/sq mi 894/km2 44.5207°N 87.9842°W
288
+ 287 Tyler Texas 104798 96900 +8.15% 56.6 sq mi 146.6 km2 1,852/sq mi 715/km2 32.3173°N 95.3059°W
289
+ 288 Wichita Falls Texas 104724 104553 +0.16% 72.2 sq mi 187.0 km2 1,450/sq mi 560/km2 33.9067°N 98.5259°W
290
+ 289 Lewisville Texas 104659 95290 +9.83% 36.7 sq mi 95.1 km2 2,852/sq mi 1,101/km2 33.0466°N 96.9818°W
291
+ 290 Burbank California 104447 103340 +1.07% 17.4 sq mi 45.1 km2 6,003/sq mi 2,318/km2 34.1901°N 118.3264°W
292
+ 291 Greeley Colorado 103990 92889 +11.95% 47.8 sq mi 123.8 km2 2,176/sq mi 840/km2 40.4153°N 104.7697°W
293
+ 292 San Mateo California 103959 97207 +6.95% 12.1 sq mi 31.3 km2 8,592/sq mi 3,317/km2 37.5603°N 122.3106°W
294
+ 293 El Cajon California 103768 99478 +4.31% 14.5 sq mi 37.6 km2 7,156/sq mi 2,763/km2 32.8017°N 116.9604°W
295
+ 294 Jurupa Valley California 103541 0 NA[31] 42.9 sq mi 111.1 km2 2,414/sq mi 932/km2 34.0026°N 117.4676°W
296
+ 295 Rialto California 103314 99171 +4.18% 22.3 sq mi 57.8 km2 4,633/sq mi 1,789/km2 34.1118°N 117.3883°W
297
+ 296 Davenport Iowa 102612 99685 +2.94% 62.9 sq mi 162.9 km2 1,631/sq mi 630/km2 41.5541°N 90.6040°W
298
+ 297 League City Texas 102010 83560 +22.08% 51.2 sq mi 132.6 km2 1,992/sq mi 769/km2 29.4901°N 95.1091°W
299
+ 298 Edison[32] New Jersey 101996 99967 +2.03% 30.1 sq mi 78.0 km2 3,389/sq mi 1,309/km2 40.5040°N 74.3494°W
300
+ 299 Davie[33] Florida 101871 91992 +10.74% 34.9 sq mi 90.4 km2 2,919/sq mi 1,127/km2 26.0791°N 80.2850°W
301
+ 300 Las Cruces New Mexico 101759 97618 +4.24% 76.9 sq mi 199.2 km2 1,323/sq mi 511/km2 32.3264°N 106.7897°W
302
+ 301 South Bend Indiana 101735 101168 +0.56% 41.4 sq mi 107.2 km2 2,457/sq mi 949/km2 41.6769°N 86.2690°W
303
+ 302 Vista California 101659 93834 +8.34% 18.7 sq mi 48.4 km2 5,436/sq mi 2,099/km2 33.1895°N 117.2386°W
304
+ 303 Woodbridge[32] New Jersey 101389 99585 +1.81% 23.3 sq mi 60.3 km2 4,351/sq mi 1,680/km2 40.5607°N 74.2927°W
305
+ 304 Renton Washington 100953 90927 +11.03% 23.4 sq mi 60.6 km2 4,314/sq mi 1,666/km2 47.4761°N 122.1920°W
306
+ 305 Lakewood[32] New Jersey 100758 92843 +8.53% 24.7 sq mi 64.0 km2 4,079/sq mi 1,575/km2 40.0771°N 74.2004°W
307
+ 306 San Angelo Texas 100702 93200 +8.05% 59.9 sq mi 155.1 km2 1,681/sq mi 649/km2 31.4411°N 100.4505°W
308
+ 307 Clinton[34] Michigan 100392 96796 +3.72% 28.1 sq mi 72.8 km2 3,573/sq mi 1,380/km2 42.5903°N 82.9170°W
@@ -1,3 +1,3 @@
1
1
  module Dreader
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/dreader.rb CHANGED
@@ -4,6 +4,10 @@ require 'roo'
4
4
  module Dreader
5
5
  # service class to implement the column DSL language
6
6
  class Column
7
+ def colref colref
8
+ @colref = colref
9
+ end
10
+
7
11
  def process &block
8
12
  @process = block
9
13
  end
@@ -13,7 +17,7 @@ module Dreader
13
17
  end
14
18
 
15
19
  def to_hash
16
- {process: @process, check: @check }
20
+ {process: @process, check: @check, colref: @colref }
17
21
  end
18
22
  end
19
23
 
@@ -32,11 +36,67 @@ module Dreader
32
36
  end
33
37
  end
34
38
 
39
+ # Utilities function to simplify importing data into
40
+ # ActiveRecords
41
+ class Util
42
+ # given a hash returned by Engine, return the same hash with
43
+ # keys directly bound to the content of the :value sub-key
44
+ #
45
+ # Example
46
+ #
47
+ # hash = {name: {value: "A", ...}, surname: {value: "B", ...}}
48
+ # simplify hash
49
+ # {name: "A", surname: "B"}
50
+ def self.simplify hash
51
+ new_hash = {}
52
+ hash.keys.map { |k| new_hash[k] = hash[k][:value] }
53
+ new_hash
54
+ end
55
+
56
+ # given a hash returned by Engine, keep the "kept" keys in the top
57
+ # of the hierarchy and move the "moved_key" below the
58
+ # "subordinate_key"
59
+ #
60
+ # Example
61
+ #
62
+ # hash = {name: "A", surname: "B", address: "via XX Settembre", city: "Genoa"}
63
+ # restructure hash, [:name, :surname], :address_attributes, [:address, :city]
64
+ # {name: "A", surname: "B", address_attributes: {address: "via XX Settembre", city: "Genoa"}}
65
+ #
66
+ def self.restructure hash, kept, subordinate_key, moved_keys
67
+ head = hash.slice kept
68
+ subordinate = self.prepend subordinate_key, hash.slice(moved_keys)
69
+ head.merge subordinate
70
+ end
71
+
72
+ # an alias for Hash.slice
73
+ def self.slice hash, *keys
74
+ hash.slice keys
75
+ end
76
+
77
+ # remove all `keys` from `hash`
78
+ def self.clean hash, keys
79
+ hash.reject { |k, v| keys.include?(k) }
80
+ end
81
+
82
+ # given a hash, return a new hash with key and whose value is
83
+ # the hash
84
+ #
85
+ # Example:
86
+ #
87
+ # hash = {name: "A", size: 10}
88
+ # prepend hash, :product_attributes
89
+ # {product_attributes: {name: "A", size: 10}}
90
+ #
91
+ def self.prepend hash, key
92
+ {key => hash}
93
+ end
94
+ end
95
+
35
96
  #
36
97
  # This is where the real stuff begins
37
98
  #
38
- class Engine
39
-
99
+ class Engine
40
100
  # readable for debugging purposes
41
101
  # the options we passed
42
102
  attr_reader :options
@@ -83,39 +143,73 @@ module Dreader
83
143
 
84
144
  # read a file and store it internally
85
145
  # return the data we read in the form of an array of hashes
86
- def read filename=nil
146
+ def read filename = nil
87
147
  spreadsheet = Dreader::Engine.open_spreadsheet (filename || @options[:filename])
88
148
  sheet = spreadsheet.sheet(@options[:sheet] || 0)
89
149
 
90
- @array = Array.new
150
+ @table = Array.new
91
151
  @errors = Array.new
92
- first_row = @options[:start_at] || 1
93
- (first_row..spreadsheet.last_row).each do |row_number|
94
- row = spreadsheet.row(row_number)
152
+
153
+ first_row = @options[:first_row] || 1
154
+ last_row = @options[:last_row] || sheet.last_row
155
+
156
+ (first_row..last_row).each do |row_number|
95
157
 
96
158
  r = Hash.new
97
159
  @colspec.each_with_index do |colspec, index|
160
+ cell = sheet.cell(row_number, colspec[:colref])
161
+
98
162
  colname = colspec[:name]
99
163
 
100
164
  r[colname] = Hash.new
101
-
102
165
  r[colname][:row_number] = row_number
103
- r[colname][:col_number] = index + 1
166
+ r[colname][:col_number] = colspec[:colref]
104
167
 
105
- r[colname][:value] = value = colspec[:process] ? colspec[:process].call(row[index]) : row[index]
168
+ r[colname][:value] = value = colspec[:process] ? colspec[:process].call(cell) : cell
106
169
 
107
170
  if colspec[:check] and not colspec[:check].call(value) then
108
171
  r[colname][:error] = true
109
- @errors << "Error: value \"#{row[index]}\" for #{colname} at row #{row_number} (col #{index + 1}) is incorrect"
172
+ @errors << "Error: value \"#{cell}\" for #{colname} at row #{row_number} (col #{index + 1}) does not pass the check function"
110
173
  else
111
174
  r[colname][:error] = false
112
175
  end
113
176
  end
114
177
 
115
- @array << r
178
+ @table << r
179
+ end
180
+
181
+ @table
182
+ end
183
+
184
+ alias_method :load, :read
185
+
186
+ # show to stdout the first `n` records we read from the file given the current
187
+ # configuration
188
+ def debug n = 10, filename = nil
189
+ spreadsheet = Dreader::Engine.open_spreadsheet (filename || @options[:filename])
190
+ sheet = spreadsheet.sheet(@options[:sheet] || 0)
191
+
192
+ puts "Current configuration:"
193
+ @options.each do |k, v|
194
+ puts " #{k}: #{v}"
195
+ end
196
+ if filename and @options[:filename] and filename != @options[:filename]
197
+ puts "Warning: you asked me to load a file different from the one specified in the otptions."
116
198
  end
117
199
 
118
- @array
200
+ first_row = @options[:first_row] || 1
201
+ puts "I will read records #{first_row} to #{n} from #{filename || @options[:filename]}"
202
+ last_row = first_row + n - 1
203
+ (first_row..last_row).each do |row_number|
204
+ puts "Record #{row_number} is:"
205
+ r = Hash.new
206
+ @colspec.each_with_index do |colspec, index|
207
+ cell = sheet.cell(row_number, colspec[:colref])
208
+ colname = colspec[:name]
209
+
210
+ puts " Field #{colname}: column %d, value \"#{cell}\"" % colspec[:colref]
211
+ end
212
+ end
119
213
  end
120
214
 
121
215
  # return an array of strings with all the errors we have encounterd
@@ -127,24 +221,25 @@ module Dreader
127
221
  # apply the mapping code to the array
128
222
  # it makes sense to invoke it only
129
223
  def process
130
- @array.each do |r|
224
+ @table.each do |r|
131
225
  @mapping.call(r)
132
226
  end
133
227
  end
134
228
 
135
229
  def to_s
136
- @array.to_s
230
+ @table.to_s
137
231
  end
138
232
 
139
233
  private
140
234
 
141
235
  def self.open_spreadsheet(filename)
142
236
  case File.extname(filename)
143
- when ".csv" then Csv.new(filename)
237
+ when ".csv" then Roo::CSV.new(filename)
238
+ when ".tsv" then Roo::CSV.new(filename, csv_options: {col_sep: "\t"})
144
239
  when ".ods" then Roo::OpenOffice.new(filename)
145
240
  when ".xls" then Roo::Excel.new(filename)
146
241
  when ".xlsx" then Roo::Excelx.new(filename)
147
- else raise "Unknown file type: #{filename}"
242
+ else raise "Unknown extension: #{File.extname(filename)}"
148
243
  end
149
244
  end
150
245
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dreader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adolfo Villafiorita
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-03-22 00:00:00.000000000 Z
11
+ date: 2018-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,12 +70,17 @@ extra_rdoc_files: []
70
70
  files:
71
71
  - ".gitignore"
72
72
  - Gemfile
73
+ - Gemfile.lock
73
74
  - LICENSE.txt
74
75
  - README.md
75
76
  - Rakefile
76
77
  - bin/console
77
78
  - bin/setup
78
79
  - dreader.gemspec
80
+ - examples/wikipedia_big_us_cities/big_us_cities.rb
81
+ - examples/wikipedia_big_us_cities/cities_by_state.ods
82
+ - examples/wikipedia_us_cities/us_cities.rb
83
+ - examples/wikipedia_us_cities/us_cities.tsv
79
84
  - lib/dreader.rb
80
85
  - lib/dreader/version.rb
81
86
  homepage: http://github.com/avillafiorita/dreader