Swap rows and columns of a list
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
-
- Posts: 121
- Joined: Thu Mar 27, 2008 10:19 am
Swap rows and columns of a list
There's an easy and fast way to swap rows and columns of a list (better than a classic "repeat" loop)?
For instance I have a list like this:
1,2,3
4,5,6
7,8,9
and I need it to convert into a list like this:
1,4,7
2,5,8
3,6,9
For instance I have a list like this:
1,2,3
4,5,6
7,8,9
and I need it to convert into a list like this:
1,4,7
2,5,8
3,6,9
Re: Swap rows and columns of a list
The following code works with any dimension list, field 1 is input and field 2 is output:
########CODE#######
on mouseUp
put field 1 into temp
set columndel to comma
split temp by column
repeat for each element tElem in temp
repeat for each line tLine in tElem
put tLine & comma after field 2
end repeat
delete last char of field 2
put return after field 2
end repeat
end mouseUp
#####END OF CODE#####
########CODE#######
on mouseUp
put field 1 into temp
set columndel to comma
split temp by column
repeat for each element tElem in temp
repeat for each line tLine in tElem
put tLine & comma after field 2
end repeat
delete last char of field 2
put return after field 2
end repeat
end mouseUp
#####END OF CODE#####
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w
-
- Posts: 121
- Joined: Thu Mar 27, 2008 10:19 am
Re: Swap rows and columns of a list
Thank you MaxV, I had already wrote this code. There's difference in speed with large list between our two codes?
Code: Select all
function swap listt, theItDel
if theItDel <> empty then set the itemDel to theItDel -- sets the desired delim
repeat with a=1 to the number of lines in listt
put line a of listt into theLine
repeat with x=1 to the number of items in theLine
put item x of theLine into item a of line x of theNewData
end repeat
end repeat
return theNewData
end swap
Re: Swap rows and columns of a list
Hi Paul,
Best
Klsud
yes, "repeat for each..." is always a lot faster that "repeat with..."!paulclaude wrote:There's difference in speed with large list between our two codes?
Best
Klsud
Re: Swap rows and columns of a list
Hi paulclaude:
MaxV's code is different from yours in that it uses it converts the list into an array.
If you can have your data in an array form, many operations are quick and efficient.
Here's a variant of MaxV's code:
Regards,
Sri
MaxV's code is different from yours in that it uses it converts the list into an array.
If you can have your data in an array form, many operations are quick and efficient.
Here's a variant of MaxV's code:
Code: Select all
on mouseUp
local temp
put field "Input" into temp
set the columnDel to comma
split temp by column
combine temp by comma
replace return with tab in temp
replace comma with return in temp
replace tab with comma in temp
put temp into field "Output"
end mouseUp
Sri
-
- Posts: 121
- Joined: Thu Mar 27, 2008 10:19 am
Re: Swap rows and columns of a list
Thanks, it's faster than my code
Re: Swap rows and columns of a list
Your code doesn't work on a 12x12, this:sritcp wrote:Hi paulclaude:
MaxV's code is different from yours in that it uses it converts the list into an array.
If you can have your data in an array form, many operations are quick and efficient.
Here's a variant of MaxV's code:
Regards,Code: Select all
on mouseUp local temp put field "Input" into temp set the columnDel to comma split temp by column combine temp by comma replace return with tab in temp replace comma with return in temp replace tab with comma in temp put temp into field "Output" end mouseUp
Sri
Code: Select all
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,70,71,72
73,74,75,76,77,78,79,80,81,82,83,84
85,86,87,88,89,90,91,92,93,94,95,96
97,98,99,100,101,102,103,104,105,106,107,108
109,110,111,112,113,114,115,116,117,118,119,120
121,122,123,124,125,126,127,128,129,130,131,132
133,134,135,136,137,138,139,140,141,142,143,144
Code: Select all
1,13,25,37,49,61,73,85,97,109,121,133
10,22,34,46,58,70,82,94,106,118,130,142
11,23,35,47,59,71,83,95,107,119,131,143
12,24,36,48,60,72,84,96,108,120,132,144
2,14,26,38,50,62,74,86,98,110,122,134
3,15,27,39,51,63,75,87,99,111,123,135
4,16,28,40,52,64,76,88,100,112,124,136
5,17,29,41,53,65,77,89,101,113,125,137
6,18,30,42,54,66,78,90,102,114,126,138
7,19,31,43,55,67,79,91,103,115,127,139
8,20,32,44,56,68,80,92,104,116,128,140
9,21,33,45,57,69,81,93,105,117,129,141
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w
Re: Swap rows and columns of a list
MaxV:
You are correct.
Arrays seem to retain the order of the columns while they are arrays, but lose the order when combined into a list.
Thanks for the insight,
Sri
You are correct.
Arrays seem to retain the order of the columns while they are arrays, but lose the order when combined into a list.
Thanks for the insight,
Sri
Re: Swap rows and columns of a list
One way to get around this problem is to save the keys and sort by them.sritcp wrote:........
Arrays seem to retain the order of the columns while they are arrays, but lose the order when combined into a list. .....
Here's above code modified to that:
Code: Select all
on mouseUp
local temp, tCounter
put field "Input" into temp
set the columnDel to comma
split temp by column
combine temp by comma and ":"
replace return with tab in temp
replace comma with return in temp
replace tab with comma in temp
set the itemDel to ":"
sort lines of temp ascending numeric by item 1 of each
put 1 into tCounter
repeat for each line tLine in temp
delete item 1 of line tCounter of temp
add 1 to tCounter
end repeat
put temp into field "Output"
end mouseUp
Regards,
Sri
Re: Swap rows and columns of a list
Hi Sri,
your solution gives correct result with the test Matrix 12:12 from above.
However in your code using the repeat for each form you modify the container you are referencing, in this case temp
the dictionary warns against this technique
In a repeat with i = 1 to x form you can change the container, that is one of the reasons why it is a lot slower than repeat for each, but not in the repeat for each form: leave the container alone.
Kind regards
Bernd
your solution gives correct result with the test Matrix 12:12 from above.
However in your code using the repeat for each form you modify the container you are referencing, in this case temp
Code: Select all
repeat for each line tLine in temp
delete item 1 of line tCounter of temp
add 1 to tCounter
end repeat
This is why I comment on this because new users of Livecode might think this is a viable technique, it is NOTImportant: In any of the for each loops, you should not change the labelVariable or container in a statement inside the loop. Doing so will not cause a script error, but will almost certainly produce unexpected results.
In a repeat with i = 1 to x form you can change the container, that is one of the reasons why it is a lot slower than repeat for each, but not in the repeat for each form: leave the container alone.
Kind regards
Bernd
Re: Swap rows and columns of a list
Hi Bernd:bn wrote:the dictionary warns against this technique .........Code: Select all
repeat for each line tLine in temp delete item 1 of line tCounter of temp add 1 to tCounter end repeat
Thanks for pointing this out. Yes, changing the container that is being looped over is dangerous.
I should have made a copy of temp and changed the copy.
Code: Select all
put temp into temp2
put 1 into tCounter
repeat for each line tLine in temp
delete item 1 of line tCounter of temp2
add 1 to tCounter
end repeat
(Of course, in this example there is no advantage to using this over "repeat with i = ..." because we are changing all lines, but if only a few lines are changed conditionally, this would preserve the speed advantage of "repeat for ....". Am I right?)
Thanks,
Sri
Re: Swap rows and columns of a list
Hi Sri,
I tested
and it is virtually equally fast.
What I do at times, which is also off-label, is to change the labelVariable since I consider the labelVariable an ordinary variable which is filled anew with each iteration. Changing the labelVariable and storing the modified labelVariable in a different container works for me reliably, although IT IS NOT WHAT THE DICTIONARY RECOMMENDS.
But I never change the container in a "for each" loop because I think the speed advantage comes from the fact that Livecode can map the delimiter (line or item etc) once before starting the "for each" loop and then relies on that map, i.e. LC does not recount the delimiters nor their location with each loop.
Kind regards
Bernd
To do the changes on a copy of the container that is looped on should not cause any trouble. As you point out it forces Livecode to count to the desired line every time.This would still let us use "repeat for ....", won't it?
(Of course, in this example there is no advantage to using this over "repeat with i = ..." because we are changing all lines, but if only a few lines are changed conditionally, this would preserve the speed advantage of "repeat for ....". Am I right?)
I tested
Code: Select all
repeat with i = 1 to the number of lines of temp
delete item 1 of line i of temp
end repeat
What I do at times, which is also off-label, is to change the labelVariable since I consider the labelVariable an ordinary variable which is filled anew with each iteration. Changing the labelVariable and storing the modified labelVariable in a different container works for me reliably, although IT IS NOT WHAT THE DICTIONARY RECOMMENDS.
But I never change the container in a "for each" loop because I think the speed advantage comes from the fact that Livecode can map the delimiter (line or item etc) once before starting the "for each" loop and then relies on that map, i.e. LC does not recount the delimiters nor their location with each loop.
Kind regards
Bernd
Re: Swap rows and columns of a list
bn wrote:..... As you point out it forces Livecode to count to the desired line every time......
Only in this specific example. If instead, we had 1000 rows, for example, and only 20 needed to be updated as a result of running the repeat loop, you should find that it is significantly faster than "repeat with i=1..." option. So, the point is still valid.bn wrote:I testedand it is virtually equally fast.Code: Select all
repeat with i = 1 to the number of lines of temp delete item 1 of line i of temp end repeat
In fact, I have been trying to get away from having to use "repeat with i=1... " as much as possible as it draws a penalty even in the relatively small (2000-2500 records) datasets I work with. Sometimes, the operations are such that "repeat for ..." just won't do. I think I have stumbled upon this trick of using a copy of the container to get around.
I am also pretty sure the same tactic would work with the labelVariable -- making a copy of the lableVariable and modifying that.
Regards,
Sri