Page 1 of 2

Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 8:14 pm
by bbanelli
Greetings to all,

is there a way to initialize array as in C?

So, instead of this:

Code: Select all

Fa(0) = 361
Fa(1) = 575
Fa(2) = 922
Fa(3) = 525
Fa(4) = 176
Fa(5) = 586
Fa(6) = 640
Fa(7) = 321
Fa(8) = 536
Fa(9) = 742
Fa(10) = 677
Fa(11) = 742
Fa(12) = 687
Fa(13) = 284
Fa(14) = 193
Fa(15) = 517
Fa(16) = 273
Fa(17) = 494
Fa(18) = 263
Fa(19) = 147
Fa(20) = 593
Fa(21) = 800
Fa(22) = 571
Fa(23) = 320
Fa(24) = 803
Fa(25) = 133
Fa(26) = 231
Fa(27) = 390
Fa(28) = 685
Fa(29) = 330
Fa(30) = 63
Fa(31) = 410
is there some elegant way such as:

Code: Select all

 Fa() = {361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410}
I could use something like this, for example:

Code: Select all

Procedure Split(Array StringArray.s(1), StringToSplit.s, Separator.s = ", ")
  Protected c = CountString(StringToSplit, Separator)
  Protected i, l = StringByteLength(Separator.s)
  Protected *p1.Character = @StringToSplit
  Protected *p2.Character = @Separator
  Protected *p = *p1
  ReDim StringArray(c)
  While i < c
    While *p1\c <> *p2\c
      *p1 + SizeOf(Character)
    Wend
    If CompareMemory(*p1, *p2, l)
      CompilerIf #PB_Compiler_Unicode
        StringArray(i) = PeekS(*p, (*p1 - *p) >> 1)
      CompilerElse
        StringArray(i) = PeekS(*p, *p1 - *p)
      CompilerEndIf
      *p1 + l
      *p = *p1
    EndIf
    i + 1
  Wend
  StringArray(c) = PeekS(*p)
  ProcedureReturn c
EndProcedure
but it just seems to be a little overkill (since I have to convert data from string to quad and it just seems wrong to begin with...), so I hope I am missing out something big (wouldn't be the first time :D).

I am close to assembling PDF417 library for PureBasic which I will gladly share owing to the fact there is not to many useful (free) information on the web and I need to stack multiple data tables in the library (few thousands numbers in several predefined arrays) so it would really be handy not to write ~4000 lines of code just to initialize arrays.

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 8:44 pm
by skywalk
If you don't mind the data in memory twice, then put your array in:
DataSection
ar1:
Data.i 0,1,2,3,4,etc...
EndDataSection
And load your array with restore/read.d loop.
No type conversion necessary.
There are many examples of this in the forum.

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 8:52 pm
by infratec
Hi,

maybe this:

Code: Select all

DataSection
  FAStart:
  Data.w 361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410
  FAEnd:
EndDataSection

Dim FA.w((?FAEnd - ?FAStart) / SizeOf(Word))

;Debug ?FAEnd - ?FAStart

Restore FAStart
For i = 1 To (?FAEnd - ?FAStart) / SizeOf(Word)
  Read.u FA(i)
  Debug Str(i) + " : " + Str(FA(i))
Next i
or simply:

Code: Select all

Debug PeekW(?FAStart + 2 * SizeOf(Word))
Than yon don't need the array. Index goes from 0 to 63.

Bernd

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 9:01 pm
by netmaestro
My entry:

Code: Select all

DataSection
  lasers:
  Data.i 345, 22, 0, 143, 17, 222, 200, 60, 19
  lasersend:
  ships:
  Data.i 98, 77, 13, 275
  shipsend:
EndDataSection

Procedure LoadArray( Array this.i(1), *addr_start, *addr_end)
  *start.integer = *addr_start
  i=0
  While *start < *addr_end
    this(i) = *start\i
    *start+SizeOf(integer)
    i+1
  Wend
EndProcedure


Dim lasers.i(8)
Dim ships.i(3)

Loadarray( lasers(), ?lasers, ?lasersend)
Loadarray( ships(), ?ships, ?shipsend)

Debug "lasers:"
For i=0 To ArraySize(lasers())
  Debug lasers(i)
Next
Debug ""
Debug "ships:"
For i=0 To ArraySize(ships())
  Debug ships(i)
Next

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 9:06 pm
by davido
@bbanelli

Please take a look at this little gem, by Little John.

http://www.purebasic.fr/english/viewtop ... 06#p446906

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 9:07 pm
by Tenaja
Here is a method I saved from another post:

Code: Select all

; Note: fills the array at definition time, but uses JSON library; may make a larger exe if you do not already use the JSON lib.

EnableExplicit

Define.i m_jArray, last, i

Macro CreateArray (_content_, _array_)
	m_jArray = ParseJSON(#PB_Any, _content_)
	If m_jArray
		Dim _array_(0)
		ExtractJSONArray(JSONValue(m_jArray), _array_())
		FreeJSON(m_jArray)
	EndIf
EndMacro


; == Demo
CreateArray("[1, 3, 5, 7, 9]", a.i)

last = ArraySize(a())
For i = 0 To last
	Debug a(i) 
Next

Debug "-----"

CreateArray("[1.5, 3.4, 5.3, 7.2, 9.1]", x.d)

last = ArraySize(x())
For i = 0 To last
	Debug StrD(x(i), 1) 
Next

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 9:08 pm
by Tenaja
davido wrote:@bbanelli

Please take a look at this little gem, by Little John.

http://www.purebasic.fr/english/viewtop ... 06#p446906
...and that must be where I got it!

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 9:16 pm
by bbanelli
davido wrote:@bbanelli

Please take a look at this little gem, by Little John.

http://www.purebasic.fr/english/viewtop ... 06#p446906
Thanks guys for sharing all the code, but this is brilliant and handy for 5.30 which I will be using for software. :)

Could this particular post be extracted and filled with key words in Tips n' Tricks to be a bit more visible and usable?

There seems to be an issue with this code above.

Code: Select all

CreateArray("[11101010111000000, 11110101011110000, 11111010101111100, 11101010011100000, 11110101001111000, 11111010100111110, 11010100011000000, 11101010001110000, ... there are 929 unique patterns..., 11000011000010010, 11001111001110100, 11000111000110010, 11011111011110100]", Table1.s)
Produces A literal string can't be bigger than 8192 characters."

Any workaround?

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 9:23 pm
by Tenaja
Here is yet another way to initialize an array with fixed data. It uses strings, but would be trivially different for numbers.

Code: Select all

    Global Dim MyArray.s(8)

    For I = 0 To 7
       Read.s MyArray(I)
       Debug MyArray(I)
    Next

    DataSection
       WordListData:
       Data.s "one"
       Data.s "two"
       Data.s "three"
       Data.s "up"
       Data.s "to"
       Data.s "fifteen"
       Data.s "chars"
       Data.s "extra text over 15 chars to be discarded"
    EndDataSection

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 9:33 pm
by bbanelli
Tenaja wrote:Here is yet another way to initialize an array with fixed data. It uses strings, but would be trivially different for numbers.

Code: Select all

    Global Dim MyArray.s(8)

    For I = 0 To 7
       Read.s MyArray(I)
       Debug MyArray(I)
    Next

    DataSection
       WordListData:
       Data.s "one"
       Data.s "two"
       Data.s "three"
       Data.s "up"
       Data.s "to"
       Data.s "fifteen"
       Data.s "chars"
       Data.s "extra text over 15 chars to be discarded"
    EndDataSection
This is almost as impractical as "standard" PureBasic initialization of array. Too bad JSON stuff won't work for large data set, as it seems... :(

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 10:17 pm
by Tenaja
bbanelli wrote:
Tenaja wrote:Here is yet another way to initialize an array with fixed data. It uses strings, but would be trivially different for numbers.
This is almost as impractical as "standard" PureBasic initialization of array. Too bad JSON stuff won't work for large data set, as it seems... :(
One of PB's biggest weaknesses is its lack of constant array initialization. However, there are numerous ways around it.

The code shown was just a "proof of concept." It is a very practical method, if you clean it up into real code. (You do know you can separate data with commas, right?) It is nearly as practical as all of the other methods. If you have multiple constant arrays, make a proc if you want; there is minimal overhead.

There is yet another way, and that is to reference the datasection directly with a pointer. I had an example, but could not find it. It can be dangerous for people who are not cautious.

And others...
...search for Array EasyFill
... For data with Structures: http://purebasic.fr/english/viewtopic.p ... 66#p411422

Re: Simple adding of bulk data to array/list

Posted: Tue Aug 26, 2014 11:58 pm
by Zebuddi123
Hi to All Maybe of Use

Code: Select all

Procedure.i Serialize_Array(string.s, Array array_name.i(1), delimeter.s)
	Protected i.i
	Nbr_Entries=CountString(string,delimeter)
	ReDim array_name(Nbr_Entries)
	For i=0 To Nbr_Entries
		array_name(i)=Val(StringField(string, i+1, delimeter))
	Next
	ProcedureReturn Nbr_Entries ; 0 = Error
EndProcedure

Procedure.i Serialize_List(string.s, List list_name.i(),  delimeter.s)
	Protected i.i
	Nbr_Entries=CountString(string,delimeter)
	If Nbr_Entries>0
		For i=1 To 	Nbr_Entries+1
			AddElement(list_name())
			list_name()=Val(StringField(string, i, delimeter))
		Next
	EndIf
	ProcedureReturn Nbr_Entries+1 ; 0 = Error
EndProcedure

Dim ary.i(1)

NewList lst.i()

s.s="361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410"

x=Serialize_List(s, lst(), ",")
x=Serialize_Array(s, ary(), ",")
or 
x=Serialize_List("361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410", lst(), ",")
x=Serialize_Array("361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410", ary(), ",")
Zebuddi. :D

Re: Simple adding of bulk data to array/list

Posted: Wed Aug 27, 2014 1:41 am
by Jagermeister
:P

Code: Select all

Fa$ = "361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410"

count = CountString(Fa$, ", ")

Dim bbanellis_numbers(a)

a = -1

For n = 1 To count + 1   ; Do a +1 if end of string doesn't have a delimiter.
  a + 1
  ReDim bbanellis_numbers(a)
  bbanellis_numbers(a) = Val(StringField(Fa$,n,", "))
  Debug bbanellis_numbers(a)
Next n

Re: Simple adding of bulk data to array/list

Posted: Wed Aug 27, 2014 4:34 am
by Tenaja
Here is one that is good for fixed-length data (not strings). Benefits are there is no setup. Drawback over transferring it to a "real" array is there is a call to PEEK, however long that function takes, plus one MOV instruction. Not bad for data that is not accessed heavily, considering there is no setup... It is certainly the fastest setup-wise of all options.

Code: Select all

DataSection     ; Put your constant data here:
	ConstantArrayData: 
		Data.i 5, 6, 7, 9, 0
EndDataSection

Macro FakeConstantArray(num)     ; edit "integer" to your datatype.
	(PeekI(?ConstantArrayData + SizeOf(integer) * num))
EndMacro

For Counter = 0 To 4		; You must prevent overflow.
	y = FakeConstantArray(Counter)
	Debug y
Next
This version is a little slower, but has an example of overflow protection:

Code: Select all

; Put your constant array data here:
DataSection
	TestData: : Data.i 5,6,7,9, 0
	TestDataOverFlow:		; this label is optional if you are already doing bounds checking.
EndDataSection

; This Macro sets the pointer to your offset. Change the argument in SizeOf(x) to match your data size.
Macro SetPointer(num)
	*TempPtr = ?testData  + SizeOf(integer) * num
EndMacro

Macro TestVariable()
	(PeekI(*TempPtr))
EndMacro

Debug "With For loop, and overflow testing:"

For Counter = 0 To 9					; intentional overflow
	SetPointer(Counter)
	If *TempPtr >= ?TestDataOverFlow	; bounds checking
		Break
	EndIf
	y = TestVariable()
	Debug y
Next

Re: Simple adding of bulk data to array/list

Posted: Wed Aug 27, 2014 5:14 am
by wilbert
Maybe the easiest way is not to use a PureBasic array but to do it like this ...

Code: Select all

Structure QuadArray
  q.q[0]
EndStructure

DataSection
  Array1Data:
  Data.q 1, 2, 3, 4, 5, 6, 7
  Array2Data:
  Data.q 1000, 2000, 3000, 4000, 5000, 6000, 7000
EndDataSection

*Array1.QuadArray = ?Array1Data
*Array2.QuadArray = ?Array2Data

Debug *Array1\q[2] + *Array2\q[4]