PDA

View Full Version : Unique values from the table


sumar
08-16-2007, 10:57 AM
Hello,

I have a several values in the table but some of them are repeated. Is there any way to take only unique values?

An example table:

483568932
345734745
435743574
435743574
435743574
324573457
345737345
345737345
345688568

And I need that as the output:

483568932
345734745
435743574
324573457
345737345
345688568

Or maybe there is any possibility to check if the value is in the table before adding, and if it is, then go to the next value...?

Thank you.

holtgrewe
08-16-2007, 11:28 AM
When working with unique entries in a table there may be several ways to handle the entries.

One would be to check the entire table each time prior to adding the entry. If the entry is not in the table then insert it.

Another way would be to sort the table and add the entry once you determine you did not encounter a duplicate and the current table entry is greater than the one being inserted.

You'll have to determine which is better for you. It depends on how much table activity you will be having, and how large the table is - Searching the table each time, or searching up to the sequential point and then sorting the table after each entry.

With a Table.Sort - if appropriate in your situation - you can test duplicates as you access the entries sequentially from the table.

There may be better solutions from the coding gurus in this forum.

sumar
08-16-2007, 11:54 AM
I have a very small table so both ways will be fine for me, but unfortunately I have no idea how to code it.

holtgrewe
08-16-2007, 12:16 PM
Here's a very rudimentary example of some untested code. It should give you an understanding of what to do.

-- table
mytable={}

--inp_text is a value to be entered into the table
new_value=inp_text

-- constraints of table ( 1 thru tmax)
tmax=Table.Count(mytable);
tDuplicate=0 -- duplicate entry switch

--Look through table to see if a duplicate exists
for loop = 1, tmax do
if new_value == mytable[loop] then tDuplicate = 1 end
end

-- insert if non dulicate
if tDuplicate == 0 then Table.Insert(mytable, tmax+1, new_value) end

HTH

usernameCasper
08-16-2007, 12:19 PM
Hey sumar,

Add this code into your project:


strConcatYourTable = Table.Concat(tblYourTable,"",1,TABLE_ALL);
tblYourTableFiltered = {};
tblYourTableFilteredCounter = 0;
for nrIndex, strValue in tblYourTable do
if String.Find(strConcatYourTable,strValue,1,true) ~= -1 then
strConcatYourTable = String.Replace(strConcatYourTable,strValue,"",true);
tblYourTableFilteredCounter = tblYourTableFilteredCounter +1;
Table.Insert(tblYourTableFiltered,tblYourTableFilt eredCounter,strValue);
end
end
strYourTableFiltered = Table.Concat(tblYourTableFiltered,"\r\n",1,TABLE_ALL);
Paragraph.SetText("YourParagraph","This is my filtered array !:\r\n\r\n"..strYourTableFiltered.."\r\n\r\nFiltered Table, counts: "..Table.Count(tblYourTableFiltered).." rows!");


Kind regards,
-Casper

sumar
08-16-2007, 12:32 PM
That's it, thank you!

usernameCasper
08-16-2007, 02:47 PM
np :)
have fun coding !

Desolator
08-16-2007, 03:28 PM
A shorter and simpler approach:

function TableOptimize(tblTableToOptimize)
-- define the new table
local tblOptTable = {};

-- browse through the table
for numOptIndex1, strOptValue1 in tblTableToOptimize do
-- browse again through the table
for numOptIndex2, strOptValue2 in tblTableToOptimize do
-- compare the two values
if strOptValue1 ~= strOptValue2 then
-- if there's no match, add it to the new table
tblOptTable[numOptIndex1] = strOptValue1;
end
end
end

-- return the new table
return tblOptTable;
end

Not tested, but should work. Just call it like:

tblBadTable ={};
tblBadTable[1] = 483568932;
tblBadTable[2] = 345734745;
tblBadTable[3] = 435743574;
tblBadTable[4] = 435743574;
tblBadTable[5] = 435743574;
tblBadTable[6] = 324573457;
tblBadTable[7] = 345737345;
tblBadTable[8] = 345737345;
tblBadTable[9] = 345688568;

tblGoodTable = TableOptimize(tblBadTable);

usernameCasper
08-17-2007, 03:14 AM
As a competition in some kind of way by certain people, I citate:
A shorter and simpler approach: lol :rolleyes

Trying to exceed it desolator? lol :wow
Maybe I put my code all into 1 line, its much shorter, think outside the box,
and why use 2 for-loops and replace a row in your array without adding like in your comment ? There are over 10 ways to do this, so ours arent the ones who's smaller imo, btw it toke me max 2 min to code and test it :)
Now we talking not only about codelines, but also about CPU-RAM performance, think outside the box please...

Desolator
08-17-2007, 06:14 AM
You need one line to call the function, instead of a ton if pasting code.

And about performance, you'd need a very slow CPU for this function to be slow. I tested one with 4 nested FORs and it executed in 300 ms working on a huge table (300+ lines) on a 575 Mhz CPU and 128 MB of SDRAM. Thus 2 nested FORs would execute in a blink.

usernameCasper
08-17-2007, 07:35 AM
yes, I know, but thats what i made in couple minutes, thus no code optimalization, you ever programmed in VB, C, java, etc. ? Its all worse than you can imagine than this related to "tons of code".
In case of the performance, its figurly, not literally, compare it to the tons of code.

Btw, nvm, we did both our job on different ways, like there could be another 100 ways to archieve this goal.

Lorne
08-17-2007, 10:34 AM
Since Lua tables are associative, there's an even faster trick you can use: just make those values indices (keys) instead of entries. Then you don't have to walk the table at all to determine whether the table contains a given value, just check for its existence.

An example to illustrate the concept:

tbl = {};
tbl[483568932] = true;
tbl[345734745] = true;
tbl[435743574] = true;

local n1 = 345688568; -- not in table
local n2 = 435743574; -- in table

-- test whether a value is in the table:
if tbl[n1] then
-- this won't happen
Dialog.Message("", "n1 found");
end

if tbl[n2] then
-- this will happen
Dialog.Message("", "n2 found");
end

You can use this technique to create tables with unique elements very efficiently. Note that you could use any non-nil value for each element, such as a string, or another table.

Using "if" to test whether a key is already in the table is appropriate for building tables when you want items to be non-overridable -- so that when trying to add the same value twice, the first one prevents the second one from being added. (This only makes sense when the elements contain information and don't just contain "true" as in the example above.)

If you aren't storing any information in each element, or if you want duplicate items to override existing ones, then you don't need to use any if test at all, and just add the items to the table as keys:

tbl = {};
tbl[483568932] = true;
tbl[345734745] = true;
tbl[435743574] = true;
tbl[435743574] = true; -- overwrites the previous value
tbl[435743574] = true; -- overwrites it again

Whichever method you use, you can just walk the table normally with a for loop to get the keys.

usernameCasper
08-17-2007, 11:14 AM
and that's even faster the way you explained, sounds AMS is pretty powerfull in my eyes :):yes

holtgrewe
08-17-2007, 02:16 PM
Lorne

...great little tidbit there on table handling. I can really put that to use.

Thanks

Lorne
08-17-2007, 03:20 PM
:)

Associative arrays are usually implemented internally as an indexed string map (e.g. using a hash table or similar indexing technique) so this trick is much, much faster than performing string comparisons in a loop, especially in an interpreted language like Lua.

I discovered this technique back in '99 when I was making scripts for Starsiege Tribes, a multiplayer online game which used an interpreted scripting language that also had associative arrays. I used it to map the standard string messages that were sent between the server and client into a number of events that other scripters could attach to. That support script ended up being used for all kinds of things, from inter-player signaling systems to things like custom ammo HUD displays and weapon-specific crosshairs.

Desolator
08-18-2007, 03:43 AM
Thanks Lorne, I forgot that tables are associative. That's a really good and simple trick.