mirror of
https://github.com/FourierTransformer/ftcsv.git
synced 2024-11-19 19:54:23 +00:00
Added rowFunc as optional parameter to ftcsv.parse
rowFunc will be called after parsing each data row as follows: output[line] = rowFunc(output[line], line) if output[line] is nil afterwards, line will not be incremented.
This commit is contained in:
parent
4a2c22fb0a
commit
7bdd4aa5bd
16
README.md
16
README.md
@ -70,6 +70,22 @@ ftcsv.parse("apple,banana,carrot", ",", {loadFromString=true, headers=false})
|
||||
local actual = ftcsv.parse("a,b,c\napple,banana,carrot", ",", options)
|
||||
```
|
||||
|
||||
- `rowFunc`
|
||||
|
||||
Applies a function to every row in the dataset. `rowFunc` will be passed a table containing the data for the row, and the row number. It should return a table which will be used in place of the original data table, or `nil` to remove the row entirely.
|
||||
|
||||
Ex: making field `a` uppercase
|
||||
```lua
|
||||
local options = {
|
||||
loadFromString=true,
|
||||
rowFunc=function(row, num)
|
||||
row.a = string.upper(row.a)
|
||||
return row
|
||||
end
|
||||
}
|
||||
local actual = ftcsv.parse("a,b,c\napple,banana,carrot", ",", options)
|
||||
```
|
||||
|
||||
- `headers`
|
||||
|
||||
Set `headers` to `false` if the file you are reading doesn't have any headers. This will cause ftcsv to create indexed tables rather than a key-value tables for the output.
|
||||
|
27
ftcsv.lua
Normal file → Executable file
27
ftcsv.lua
Normal file → Executable file
@ -122,7 +122,7 @@ local function createField(inputString, quote, fieldStart, i, doubleQuoteEscape)
|
||||
end
|
||||
|
||||
-- main function used to parse
|
||||
local function parseString(inputString, inputLength, delimiter, i, headerField, fieldsToKeep)
|
||||
local function parseString(inputString, inputLength, delimiter, i, headerField, fieldsToKeep, rowFunc)
|
||||
|
||||
-- keep track of my chars!
|
||||
local currentChar, nextChar = sbyte(inputString, i), nil
|
||||
@ -240,11 +240,21 @@ local function parseString(inputString, inputLength, delimiter, i, headerField,
|
||||
-- print("fs:", fieldStart)
|
||||
end
|
||||
|
||||
-- incrememnt for new line
|
||||
-- check the column count
|
||||
if fieldNum < initialLineCount then
|
||||
error('ftcsv: too few columns in row ' .. lineNum)
|
||||
end
|
||||
lineNum = lineNum + 1
|
||||
|
||||
-- transform the row using the supplied function
|
||||
if rowFunc then
|
||||
outResults[lineNum] = rowFunc(outResults[lineNum], lineNum)
|
||||
end
|
||||
|
||||
-- incrememnt for new line, if row transformation hasn't removed the current row.
|
||||
if outResults[lineNum] then
|
||||
lineNum = lineNum + 1
|
||||
end
|
||||
|
||||
outResults[lineNum] = {}
|
||||
fieldNum = 1
|
||||
fieldStart = i + 1 + skipChar
|
||||
@ -284,6 +294,10 @@ local function parseString(inputString, inputLength, delimiter, i, headerField,
|
||||
-- otherwise there might not be enough line
|
||||
elseif finalLineCount < initialLineCount then
|
||||
error('ftcsv: too few columns in row ' .. lineNum)
|
||||
|
||||
-- else it is a fully-formed line, so do row transformation if required.
|
||||
elseif rowFunc then
|
||||
outResults[lineNum] = rowFunc(outResults[lineNum], lineNum)
|
||||
end
|
||||
|
||||
return outResults
|
||||
@ -300,6 +314,7 @@ function ftcsv.parse(inputFile, delimiter, options)
|
||||
local fieldsToKeep = nil
|
||||
local loadFromString = false
|
||||
local headerFunc
|
||||
local rowFunc
|
||||
if options then
|
||||
if options.headers ~= nil then
|
||||
assert(type(options.headers) == "boolean", "ftcsv only takes the boolean 'true' or 'false' for the optional parameter 'headers' (default 'true'). You passed in '" .. tostring(options.headers) .. "' of type '" .. type(options.headers) .. "'.")
|
||||
@ -330,6 +345,10 @@ function ftcsv.parse(inputFile, delimiter, options)
|
||||
assert(type(options.headerFunc) == "function", "ftcsv only takes a function value for optional parameter 'headerFunc'. You passed in '" .. tostring(options.headerFunc) .. "' of type '" .. type(options.headerFunc) .. "'.")
|
||||
headerFunc = options.headerFunc
|
||||
end
|
||||
if options.rowFunc ~= nil then
|
||||
assert(type(options.rowFunc) == "function", "ftcsv only takes a function value for optional parameter 'rowFunc'. You passed in '" .. tostring(options.rowFunc) .. "' of type '" .. type(options.rowFunc) .. "'.")
|
||||
rowFunc = options.rowFunc
|
||||
end
|
||||
end
|
||||
|
||||
-- handle input via string or file!
|
||||
@ -389,7 +408,7 @@ function ftcsv.parse(inputFile, delimiter, options)
|
||||
end
|
||||
end
|
||||
|
||||
local output = parseString(inputString, inputLength, delimiter, i, headerField, fieldsToKeep)
|
||||
local output = parseString(inputString, inputLength, delimiter, i, headerField, fieldsToKeep, rowFunc)
|
||||
return output
|
||||
end
|
||||
|
||||
|
@ -158,6 +158,19 @@ describe("csv features", function()
|
||||
assert.are.same(expected, actual)
|
||||
end)
|
||||
|
||||
it("should make column A uppercase via rowFunc", function()
|
||||
local expected = {}
|
||||
expected[1] = {}
|
||||
expected[1].a = "APPLE"
|
||||
expected[1].b = "banana"
|
||||
expected[1].c = "carrot"
|
||||
local actual = ftcsv.parse("a,b,c\napple,banana,carrot", ",", {loadFromString=true, rowFunc=function(row)
|
||||
row.a = string.upper(row.a)
|
||||
return row
|
||||
end})
|
||||
assert.are.same(expected, actual)
|
||||
end)
|
||||
|
||||
it("should handle encoding files", function()
|
||||
local expected = {}
|
||||
expected[1] = {}
|
||||
@ -191,4 +204,4 @@ describe("csv features", function()
|
||||
assert.are.same(expected, actual)
|
||||
end)
|
||||
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user