Log In  

Hello.

Could someone help me with this please ? I'm trying to understand how this works.

var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

for i in all(var) do
  print(i.." "..var)
end

And yes, I know I can use:

var={["playhp"]=500,["playname"]="patrick",["wepname"]="dagger",["wepstr"]=2}

But I want to be able to iterate each item per line and in any order, and the ability to remove them as well.

var["playhp"]=nil

And to recall a value: print(var."playhp") returns 500. And ability to recall a value be reference:

varname="playhp"
print([email protected]) also to return 500.

And print(#var) to return 4, currently returns 0 (zero).

Thanks in advance !

P#68005 2019-09-22 21:28 ( Edited 2019-09-22 23:01)

for key,value in pairs(var) do
  print(key.." "..value)
end

"#var" only works for contiguous integer-indexed tables
so I think you'll need to

count = 0
for key in pairs(var) do count++ end
P#68007 2019-09-22 21:51

oh, and also

varname="playhp"
print(var.playhp)
print(var[varname])
P#68008 2019-09-22 21:56
:: dw817

I was wondering about PAIRS() but couldn't find enough information for my exact example. Let me try what you did here.

Phew ! That got it. Let me try your counter.

Count++ is not recognized, shame, looks like an interesting shortcut, changed to count+=1 ... then it worked !

Experimenting on single variable view.
Ah ! This works. varname="playhp" print(var.varname)

Awesome, thank you so much, ultrabrite ! :D

This is all very new territory for me. both yield() and pairs().

Years ago I made a type of Virtual Variable Minder thing for S2 which allowed you 7-characters for variable name and 8-characters for the contents. Why 7 instead of 8 ? The 1st character was ">" and it was all neatly stored in a string that could go up to 32760-characters in size. You could use INSTR to search for ">" followed by the up-to-7-character name. At the time I thought it was a pretty good method, had a sort routine, import/export to file, etc.

exciting stuff ! Will try to put this new method above to good use.
Marking this part of the question complete.

Looks like I still have a few questions. See below.

P#68009 2019-09-22 22:00 ( Edited 2019-09-22 23:19)
:: dw817

Hmm ... These are the correct answers, it is odd that PAIRS() returns the items in any random order. Is there a way to return them sorted ?

It does actually say in the instructions,

"Order is not guaranteed."

How difficult can it be to display the paired items in the order in which they are received ?

And this doesn't work to display them sorted by virtual variable name, it may require PAIRS() since there are =2= values, a virtual variable and its contents.

for i,key in all(var) do
  print(var.i.." "..var.key)
end
P#68010 2019-09-22 22:36 ( Edited 2019-09-22 23:02)
:: dw817

Surely this can be improved upon.

var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

sort1={} sort2={} sp=0
cls()
for k,v in pairs(var) do
  sort1[sp]=k sort2[sp]=v
  print(k.." "..v)
  sp+=1
end
repeat
  ok=1
  for i=0,sp-2 do
    if sort1[i]>sort1[i+1] then
      sort1[i],sort1[i+1]=sort1[i+1],sort1[i]
      sort2[i],sort2[i+1]=sort2[i+1],sort2[i]
      ok=0
    end
  end--next i
until ok==1
?""
for i=0,sp-1 do
  print(sort1[i].." "..sort2[i])
end
P#68011 2019-09-22 23:01 ( Edited 2019-09-22 23:06)

Lua tables have two parts: Sequence and non-sequence.

A sequence is represented under the hood as a simple array. The function all() (or ipairs() in standard Lua) iterates over the sequence, which are all the elements from index 1 and until the first nil. Order is guaranteed, since the indices are in order.

The non-sequence part of the table is represented as a dictionary, hash table, associative array or whatever your favorite programming language calls it. The function pairs() iterates over all index/element pairs in the table, whether they're part of the sequence or not. Order is not guaranteed, because the index can be anything and what it means to "order" those indices is not defined.

Standard Lua has table.sort for this, but in PICO-8 we need to implement it ourselves, as with so much else. Solutions have been discussed at length before: https://www.lexaloffle.com/bbs/?tid=2477

P#68025 2019-09-23 11:18
:: dw817

Hi Tobiasvl. Thanks for the reply.

While this is good information for a sort, I think what I'm looking for is a way to use "for var in all" with the data above:

var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

Then it would be automatically sorted. At least I think so.

P#68032 2019-09-23 15:07

@dw817 I think what @tobiasvl is saying is that if you want what you're asking for, you have to implement it yourself and there's no real "right way" to do that, as per the linked discussion.

P#68035 2019-09-23 16:07
:: dw817

Well ratz. There are some good sort routines, better than what I wrote. Will go to look there, MBoffin.

Yet is there any technical reason why "Order is not guaranteed" ?

I mean I can understand them not being sorted but not to even be viewed in the order they are inserted and TRULY they appear to be in random order each time you run gets my head-a-scratchin'.

var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

repeat
cls()
for k,v in pairs(var) do
  print(k.." "..v)
end
repeat
until btnp(4)
until forever

Press CTRL+R to see order rearrange each time.

P#68039 2019-09-23 17:53 ( Edited 2019-09-23 17:53)

Keeping a non-sequence ordered would still introduce an overhead though. The nice thing about a hash map is that insertion, removal and lookup are all really quick (they're O(1) in big-O notation), since all you need to do is compute the hash of the key to find the value.

To keep the insertion order, you need to sacrifice something. If you just keep the order value of each element, then deleting an element will take more time (O(N)) since you need to change the order for all subsequent elements. You can use a linked list, but that'll cost more memory. In both cases the extra information needs to be book-kept alongside the actual hash map, so you'd need to keep two data structures in sync at all times.

Hash maps/tables/dictionaries just don't bother with all that. The expectation is simply that they're kept efficient and sweet, not bothering with insertion order. No language I know of retain that information in their regular hash map data structures, although some offer one (like Python's OrderedDict). Lua, however, is a very simple language with a small core library.

If you make your own data structure that retains order (can probably be done pretty easily with metatables?) then be sure to report back how memory or CPU efficiency is affected!

So the reason it's not ordered is because that'd defeat the entire purpose of the non-sequence part of the table. If you want an ordered sequence of string/value pairs, then put those into a regular sequence as two-element tables, for example.

In Lua, the non-sequence part is often used as "object attributes" of a sort, so you write var.playhp or var.playname. In an object-oriented language, would you be surprised that an object's instance variables are not ordered?

P#68042 2019-09-23 18:30 ( Edited 2019-09-23 18:39)
:: dw817
var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

Let me ask this then. Is it possible to use a FOR IN/DO statement with the data above ? Not using PAIRS() - and will list out the entries I made.

FOR i in all(var) do
  print(valu(i,key).." "..data(valu(i,key)))
END

. . .

As far as being surprised, yes, I would be. When I wrote S2 years ago I had in it a virtual-variable minder and it always kept the values alphabetical. You had an option to reverse it, or to sort by their keys also in forward or reverse order. Of course it really didn't reverse sort, it just output the results in reverse order so the user could debug something in that format if need be.

P#68047 2019-09-23 19:15 ( Edited 2019-09-23 19:25)

Without using pairs(), no, it's not possible with the data you've provided. You need to use pairs() (that's what it's for) or change your data structure.

If you write a valu() and data() function that does exactly that for you, then you've implemented what I mentioned in my last comment: A wrapper around a hash table that takes care of internal ordering, adding some overhead along the way.

P#68051 2019-09-23 19:46 ( Edited 2019-09-23 19:47)
:: dw817

Tobiasvl, what code that you could supply would be the best way to implement that ?

I mean I know I can do it with a fat string variable like S2 but there should be a simpler way for P8 to maintain natural actual order instead of artificially infusing it.

P#68052 2019-09-23 20:01
:: dw817

Wait ... I think I can do this sort of ...

-- virtual variable minder

function addvar(a,b)
local t={}
  t.valu=a
  t.data=b
  add(var,t)
end

cls()  
var={}

addvar("playhp",500)
addvar("playname","patrick")
addvar("wepname","dagger")
addvar("wepstr",2)

for i in all(var) do
  print(i.valu.." "..i.data)
end

That's a start, but then how would I access something like.

print(result(var,"playhp"))
result would be 500

WITHOUT going through every item in a FOR/DO loop.

P#68055 2019-09-23 20:17

What do you mean by "artificially infusing"? Doing it manually? You can use metatables to create a new kind of data structure. Here are some suggestions (vanilla Lua, but I'm pretty sure they should work in PICO-8 now that we have rawset()): http://lua-users.org/wiki/OrderedTable

In your example above you trade away lookup efficiency, which you probably don't want to do. You want to trade away deletion efficiency (ie. the only thing you give up, besides some memory to store the order, is the fact that you need to re-order elements when you remove them).

P#68056 2019-09-23 20:30 ( Edited 2019-09-23 20:33)
:: dw817

This is good reading ! I'll check here ...
Thanks, Tobiasvl.

P#68058 2019-09-23 20:34
:: dw817

Not to leave you hanging, tobiasvl, I think I'll stick with the PAIRS() method.

Artificially infusing to me is making something in code that appears to be simple work to the outside viewer but in fact is a pain to write for the actual programmer because of the language's limitations either believed or actual.

Artificially infuse in this case meaning for me - that I have to write my own sort routine to see a sorted PAIRS() list.

I only need the sort to appear visually, it does not make any difference their actual position later - so I can definitely chalk up a quick view the PAIRS by sort if need be.

Here's hoping future PICO gives us a robust INSTR(), RINSTR(), and REPLACE() later. I could work with these commands and always ensure my virtual variables are sorted alphabetically at all times and even from a single string. :)

P#68062 2019-09-23 21:46 ( Edited 2019-09-23 21:50)

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2020-06-06 11:40 | 0.051s | 2097k | Q:49