mirror of
https://github.com/FourierTransformer/ftcsv.git
synced 2024-12-16 05:24:21 +00:00
Added rowTable option to ftcsv.parse()
rowTable makes ftcsv.parse() store rows in an existing table, which allows merging of multiple CSV files.
This commit is contained in:
parent
4a2c22fb0a
commit
e5b52d0eb1
13
README.md
13
README.md
@ -88,6 +88,19 @@ ftcsv.parse("apple,banana,carrot", ",", {loadFromString=true, headers=false})
|
|||||||
|
|
||||||
In the above example, the first field becomes 'a', the second field becomes 'b' and so on.
|
In the above example, the first field becomes 'a', the second field becomes 'b' and so on.
|
||||||
|
|
||||||
|
- `rowTable`
|
||||||
|
|
||||||
|
If you want to merge multiple CSV files, you can set `rowTable` to be an existing table to which ftcsv will append new rows.
|
||||||
|
|
||||||
|
Note: headers are not compared between multiple datasets. If there is a mismatch between headers of different CSV files, then rows from each CSV file will have missing fields.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local options = {loadFromString=true, rename={["a"] = "d", ["b"] = "e", ["c"] = "f"}}
|
||||||
|
local actual = ftcsv.parse("a,b,c\r\napple,banana,carrot", ",", options)
|
||||||
|
options.rowTable = actual
|
||||||
|
ftcsv.parse("a,b,c\r\ndamson,elderberry,fig", ",", options)
|
||||||
|
```
|
||||||
|
|
||||||
For all tested examples, take a look in /spec/feature_spec.lua
|
For all tested examples, take a look in /spec/feature_spec.lua
|
||||||
|
|
||||||
|
|
||||||
|
19
ftcsv.lua
19
ftcsv.lua
@ -122,7 +122,7 @@ local function createField(inputString, quote, fieldStart, i, doubleQuoteEscape)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- main function used to parse
|
-- main function used to parse
|
||||||
local function parseString(inputString, inputLength, delimiter, i, headerField, fieldsToKeep)
|
local function parseString(outResults, inputString, inputLength, delimiter, i, headerField, fieldsToKeep)
|
||||||
|
|
||||||
-- keep track of my chars!
|
-- keep track of my chars!
|
||||||
local currentChar, nextChar = sbyte(inputString, i), nil
|
local currentChar, nextChar = sbyte(inputString, i), nil
|
||||||
@ -141,7 +141,6 @@ local function parseString(inputString, inputLength, delimiter, i, headerField,
|
|||||||
local delimiterByte = sbyte(delimiter)
|
local delimiterByte = sbyte(delimiter)
|
||||||
|
|
||||||
local assignValue
|
local assignValue
|
||||||
local outResults
|
|
||||||
-- the headers haven't been set yet.
|
-- the headers haven't been set yet.
|
||||||
-- aka this is the first run!
|
-- aka this is the first run!
|
||||||
if headerField == nil then
|
if headerField == nil then
|
||||||
@ -153,8 +152,9 @@ local function parseString(inputString, inputLength, delimiter, i, headerField,
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- print("this is for magic")
|
-- print("this is for magic")
|
||||||
outResults = {}
|
outResults = outResults or {}
|
||||||
outResults[1] = {}
|
lineNum = #outResults + 1
|
||||||
|
outResults[lineNum] = {}
|
||||||
assignValue = function()
|
assignValue = function()
|
||||||
if not pcall(function()
|
if not pcall(function()
|
||||||
outResults[lineNum][headerField[fieldNum]] = field
|
outResults[lineNum][headerField[fieldNum]] = field
|
||||||
@ -300,6 +300,7 @@ function ftcsv.parse(inputFile, delimiter, options)
|
|||||||
local fieldsToKeep = nil
|
local fieldsToKeep = nil
|
||||||
local loadFromString = false
|
local loadFromString = false
|
||||||
local headerFunc
|
local headerFunc
|
||||||
|
local rowTable = {}
|
||||||
if options then
|
if options then
|
||||||
if options.headers ~= nil 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) .. "'.")
|
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 +331,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) .. "'.")
|
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
|
headerFunc = options.headerFunc
|
||||||
end
|
end
|
||||||
|
if options.rowTable ~= nil then
|
||||||
|
assert(type(options.rowTable) == "table", "ftcsv only takes in a table for the optional parameter 'rowTable'. You passed in '" .. tostring(options.rowTable) .. "' of type '" .. type(options.rowTable) .. "'.")
|
||||||
|
rowTable = options.rowTable
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- handle input via string or file!
|
-- handle input via string or file!
|
||||||
@ -347,7 +352,7 @@ function ftcsv.parse(inputFile, delimiter, options)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- parse through the headers!
|
-- parse through the headers!
|
||||||
local headerField, i = parseString(inputString, inputLength, delimiter, 1)
|
local headerField, i = parseString(nil, inputString, inputLength, delimiter, 1)
|
||||||
i = i + 1 -- start at the next char
|
i = i + 1 -- start at the next char
|
||||||
|
|
||||||
-- make sure a header isn't empty
|
-- make sure a header isn't empty
|
||||||
@ -389,8 +394,8 @@ function ftcsv.parse(inputFile, delimiter, options)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local output = parseString(inputString, inputLength, delimiter, i, headerField, fieldsToKeep)
|
rowTable = parseString(rowTable, inputString, inputLength, delimiter, i, headerField, fieldsToKeep)
|
||||||
return output
|
return rowTable
|
||||||
end
|
end
|
||||||
|
|
||||||
-- a function that delimits " to "", used by the writer
|
-- a function that delimits " to "", used by the writer
|
||||||
|
@ -21,6 +21,22 @@ describe("csv features", function()
|
|||||||
assert.are.same(expected, actual)
|
assert.are.same(expected, actual)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("should handle merging multiple datasets", function()
|
||||||
|
local expected = {}
|
||||||
|
expected[1] = {}
|
||||||
|
expected[1].a = "apple"
|
||||||
|
expected[1].b = "banana"
|
||||||
|
expected[1].c = "carrot"
|
||||||
|
expected[2] = {}
|
||||||
|
expected[2].b = "banana"
|
||||||
|
expected[2].c = "carrot"
|
||||||
|
expected[2].d = "damson"
|
||||||
|
expected[2].e = "elderberry"
|
||||||
|
local actual = ftcsv.parse("a,b,c\napple,banana,carrot", ",", {loadFromString=true})
|
||||||
|
ftcsv.parse("b,c,d,e\nbanana,carrot,damson,elderberry", ",", {loadFromString=true, rowTable=actual})
|
||||||
|
assert.are.same(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
it("should handle renaming a field", function()
|
it("should handle renaming a field", function()
|
||||||
local expected = {}
|
local expected = {}
|
||||||
expected[1] = {}
|
expected[1] = {}
|
||||||
|
Loading…
Reference in New Issue
Block a user