Currently my code have simple tables containing the data needed for each object like this:
infantry = {class = "army", type = "human", power = 2}
cavalry = {class = "panzer", type = "motorized", power = 12}
battleship = {class = "navy", type = "motorized", power = 256}
I use the tables names as identifiers in various functions to have their values processed one by one as a function that is simply called to have access to the values.
Now I want to have this data stored in a spreadsheet (csv file) instead that looks something like this:
Name class type power
Infantry army human 2
Cavalry panzer motorized 12
Battleship navy motorized 256
The spreadsheet will not have more than 50 lines and I want to be able to increase columns in the future.
Tried a couple approaches from similar situation I found here but due to lacking skills I failed to access any values from the nested table. I think this is because I don't fully understand how the tables structure are after reading each line from the csv file to the table and therefore fail to print any values at all.
If there is a way to get the name,class,type,power from the table and use that line just as my old simple tables, I would appreciate having a educational example presented. Another approach could be to declare new tables from the csv that behaves exactly like my old simple tables, line by line from the csv file. I don't know if this is doable.
Using Lua 5.1
You can read the csv file in as a string . i will use a multi line string here to represent the csv.
gmatch with pattern [^\n]+ will return each row of the csv.
gmatch with pattern [^,]+ will return the value of each column from our given row.
if more rows or columns are added or if the columns are moved around we will still reliably convert then information as long as the first row has the header information.
The only column that can not move is the first one the Name column if that is moved it will change the key used to store the row in to the table.
Using gmatch and 2 patterns, [^,]+ and [^\n]+, you can separate the string into each row and column of the csv. Comments in the following code:
local csv = [[
Name,class,type,power
Infantry,army,human,2
Cavalry,panzer,motorized,12
Battleship,navy,motorized,256
]]
local items = {} -- Store our values here
local headers = {} --
local first = true
for line in csv:gmatch("[^\n]+") do
if first then -- this is to handle the first line and capture our headers.
local count = 1
for header in line:gmatch("[^,]+") do
headers[count] = header
count = count + 1
end
first = false -- set first to false to switch off the header block
else
local name
local i = 2 -- We start at 2 because we wont be increment for the header
for field in line:gmatch("[^,]+") do
name = name or field -- check if we know the name of our row
if items[name] then -- if the name is already in the items table then this is a field
items[name][headers[i]] = field -- assign our value at the header in the table with the given name.
i = i + 1
else -- if the name is not in the table we create a new index for it
items[name] = {}
end
end
end
end
Here is how you can load a csv using the I/O library:
-- Example of how to load the csv.
path = "some\\path\\to\\file.csv"
local f = assert(io.open(path))
local csv = f:read("*all")
f:close()
Alternative you can use io.lines(path) which would take the place of csv:gmatch("[^\n]+") in the for loop sections as well.
Here is an example of using the resulting table:
-- print table out
print("items = {")
for name, item in pairs(items) do
print(" " .. name .. " = { ")
for field, value in pairs(item) do
print(" " .. field .. " = ".. value .. ",")
end
print(" },")
end
print("}")
The output:
items = {
Infantry = {
type = human,
class = army,
power = 2,
},
Battleship = {
type = motorized,
class = navy,
power = 256,
},
Cavalry = {
type = motorized,
class = panzer,
power = 12,
},
}
I'm writing a Matlab script where I have a bunch of objects of a same self defined class, say A, B and C. Then I have a function that work on any of the 2 objects, like func(A,B).
Now I want to pick an object, say A, and then func(A,x) through all the other objects. So basically achieve something like:
func(A,B)
func(A,C)
A.update()
func(B,A)
func(B,C)
B.update()
...
So I need to create an array of all the objects I can loop through, while excluding itself of course. I tried to do it with cell array, so I have:
AllObjs = {A,B,C}
for i=1:length(AllObjs)
if ~isequal(A, AllObjs{i})
func(A, AllObjs{i})
end
end
A.update()
However, when A is updated, the A in AllObjs doesn't get updates. So for the next loop I have to create a new array of all the objects. It's doable in this simple example but not manageable when the objects get updated elsewhere. So I would like to have an array of pointers to all the objects. My Google search tells me there's no pointer in Matlab, but is there a way to achieve what I want to do here?
I suspect (its difficult without seeing your code) your classes A, B & C do not inherit from from handle.
Take the examples below:
classdef noHandle
properties
name = '';
end
methods
function obj = noHandle ( name )
obj.name = name;
end
end
end
A = noHandle ( 'A' );
B = noHandle ( 'B' );
C = noHandle ( 'C' );
allObjs = { A B C }
allObjs{1}.name % check its name is "A"
% change the name of A
A.name = 'AAA'
allObjs{1}.name % see that allObjs{1} is still A.
However if you do:
classdef fromHandle < handle
properties
name = '';
end
methods
function obj = fromHandle ( name )
obj.name = name;
end
end
end
Then do:
A = fromHandle ( 'A' );
B = fromHandle ( 'B' );
C = fromHandle ( 'C' );
allObjs = { A B C }
allObjs{1}.name % check its name is "A"
% change the name of A
A.name = 'AAA'
allObjs{1}.name % see that allObjs{1} is updated to AAA.
I have a SQL column named "details" and it contains the following data:
<changes><RoundID><new>8394</new></RoundID><RoundLeg><new>JAYS CLOSE AL6 Odds(1 - 5)</new></RoundLeg><SortType><new>1</new></SortType><SortOrder><new>230</new></SortOrder><StartDate><new>01/01/2009</new></StartDate><EndDate><new>01/01/2021</new></EndDate><RoundLegTypeID><new>1</new></RoundLegTypeID></changes>
<changes><RoundID><new>8404</new></RoundID><RoundLeg><new>HOLLY AREA AL6 (1 - 9)</new></RoundLeg><SortType><new>1</new></SortType><SortOrder><new>730</new></SortOrder><StartDate><new>01/01/2009</new></StartDate><EndDate><new>01/01/2021</new></EndDate><RoundLegTypeID><new>1</new></RoundLegTypeID></changes>
<changes><RoundID><new>8379</new></RoundID><RoundLeg><new>PRI PARK AL6 (1 - 42)</new></RoundLeg><SortType><new>1</new></SortType><SortOrder><new>300</new></SortOrder><StartDate><new>01/01/2009</new></StartDate><EndDate><new>01/01/2021</new></EndDate><RoundLegTypeID><new>1</new></RoundLegTypeID></changes>
What is the easiest way to separate this data out into individual columns? (that is all one column)
Try this:
SELECT DATA.query('/changes/RoundID/new/text()') AS RoundID
,DATA.query('/changes/RoundLeg/new/text()') AS RoundLeg
,DATA.query('/changes/SortType/new/text()') AS SortType
-- And so on and so forth
FROM (SELECT CONVERT(XML, Details) AS DATA
FROM YourTable) AS T
Once you get your result set from the sql (mysql or whatever) you will probably have an array of strings. As I understand your question, you wanted to know how to extract each of the xml nodes that were contained in the string that was stored in the column in question. You could loop through the results from the sql query and extract the data that you want. In php it would look like this:
// Set a counter variable for the first dimension of the array, this will
// number the result sets. So for each row in the table you will have a
// number identifier in the corresponding array.
$i = 0;
$output = array();
foreach($results as $result) {
$xml = simplexml_load_string($result);
// Here use simpleXML to extract the node data, just by using the names of the
// XML Nodes, and give it the same name in the array's second dimension.
$output[$i]['RoundID'] = $xml->RoundID->new;
$output[$i]['RoudLeg'] = $xml->RoundLeg->new;
// Simply create more array items here for each of the elements you want
$i++;
}
foreach ($output as $out) {
// Step through the created array do what you like with it.
echo $out['RoundID']."\n";
var_dump($out);
}
I have the following array of references to arrays:
my #holidays = [[2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']];
Which are IRS recognized legal holidays during 2012. I would like to match the array #dueDate to a value in that array and return 1 or true if it is present.
while ($holidays[#dueDate]){
print ("Found Holiday \t join('-',#dueDate)");
#dueDate = Add_Delta_Days(#dueDate, 1);
if ( Day_of_Week(#dueDate) > 5){
#dueDate = Monday_of_Week((Week_Number(#dueDate)+1), $dueDate[0]);
}
}
Is my current attempt at this - the condition of the while statement is never true. I've tried a few different combinations of referencing and dereferencing holidays to no avail.
What would the best way be to manipulate the evaluation within the while statement such that the block executes when #dueDate contains a date within my array above.
Note: #dueDate is a Date::Calc standard array - (Year, Month, Day)
This should put you on the right track. Two problems I see with your code - an array of arrays should have normal parentheses on the outer part, and use the ~~ operator to compare arrays for equality.
my #holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],
[2012,'05','28'],[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],
[2012,'11','22'],[2012,'12','25']);
my $i;
my #duedate = [2012, '01', '02'];
for ($i = 0; $i < #holidays; $i++)
{
if (#holidays[$i] ~~ #duedate)
{
print "matched!!";
}
}
First,
my #holidays = [[2012,'01','02'],...,[2012,'12','25']];
should be
my #holidays = ([2012,'01','02'],...,[2012,'12','25']);
You're creating an array with a single element.
Probably the best way to achieve what you want is to use a hash.
my %holidays = map { join('-', #$_) => 1 } #holidays;
Then all you need is
while ($holidays{join('-', #dueDate)}) {
my $dow = Day_of_Week(#dueDate);
#dueDate = Add_Delta_Days(#dueDate,
$dow == 5 || $dow == 6 ? 8 - $dow : 1);
}
This is my answer, working on Perl 5.14, also I use smartmatching ~~ operator to compare two arrays.
You assign to array #holidays = [[2012,'01','02'], ]; isn't correct actually you assign anonymous array [ ['2012', '01', '02'], ] to first element of #holidays.
use v5.14;
my #holidays = ( ['2012', '01', '02'], ['2012', '01', '16'] );
my #due_date = ( '2012', '01', '16' );
for my $holiday (#holidays) {
if (#$holiday ~~ #due_date) {
say "holiday match";
}
}
Okay, a few things:
1: Lists are contained in parentheses, and literal array references are written between brackets. So, you should have:
my #holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],
[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']);
2: When you look at $holidays[#dueDate], you're calling everything in scalar context. In particular, since #dueDate has three elements, you're only looking at $holidays[3].
3: Unless you're writing a piece of throwaway code, always use strict; and use warnings;.
So, you want something like this:
use strict;
use warnings;
my #holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],
[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']);
my #dueDates=([2012,'01','01'],[2012,'01','02'],[2012,'01','03']); #Or whatever
my #due_dates_that_are_holidays=();
foreach my $due_date(#dueDates)
{
foreach my $holiday(#holidays)
{
my ($h_y,$h_m,$h_d)=#$holiday; #Capturing year month and day from the array reference
my ($d_y,$d_m,$d_d)=#$due_date; #Ditto for the due date
if($h_y == $d_y and $h_m eq $d_m and $h_d eq $d_d)
{
push #due_dates_that_are_holidays,$due_date;
}
}
}
print join("-",#{$_}) . "\n" foreach(#due_dates_that_are_holidays);
The above code produces the following output:
2012-01-02