Table.remove() issue with the last element

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Table.remove() issue with the last element

Laurent FAILLIE
Hello,

I'm facing an issue with table.remove when I would like to remove the last element of a table.
I have the following code :

xtbl = {
[1] = { "A" },
[2.5] = { "A", "B" },
[.5] = { "A" },
[5] = { "A", "B", "C" }
}

function dump(tbl)
    for i,f in pairs(tbl) do
        print(i, #f, f)

        for k,v in ipairs(f) do
            print('  ---', k, v)
        end
    end
end

function remove(tbl, func)
    for i, f in pairs( tbl ) do
        for k,v in ipairs(f) do
            if v == func then
                table.remove(f, k)
            end
        end
        if #f == 0 then
print('** remove', i)
            table.remove(tbl, i)
        end
    end
end

dump(xtbl)
remove(xtbl, 'A')

print("Resultat")
dump(xtbl)

But the result is the following :

1    1    table: 0x59d3c8
  ---    1    A
5    3    table: 0x59e0d8
  ---    1    A
  ---    2    B
  ---    3    C
2.5    2    table: 0x59d1d0
  ---    1    A
  ---    2    B
0.5    1    table: 0x59e0b0
  ---    1    A
** remove    1
** remove    0.5
Resultat
5    2    table: 0x59e0d8
  ---    1    B
  ---    2    C
2.5    1    table: 0x59d1d0
  ---    1    B
0.5    0    table: 0x59e0b0

As you can see, the sub table '1' is correctly removed. The code said as well it removed 0.5 entry ... but I dumped it, I still have it with a 0 sized sub table.
Why ? What I've missed ?

Thanks

Laurent
Reply | Threaded
Open this post in threaded view
|

Re: Table.remove() issue with the last element

Doug Currie
On Mon, Jun 20, 2016 at 4:36 PM, Laurent FAILLIE <[hidden email]> wrote:
Hello,

I'm facing an issue with table.remove when I would like to remove the last element of a table.

You should change

 table.remove(tbl, i)

to 

 tbl[i] = nil

e
Reply | Threaded
Open this post in threaded view
|

Re: Table.remove() issue with the last element

Laurent FAILLIE
Le Mardi 21 juin 2016 0h00, Doug Currie <[hidden email]> a écrit :



> You should change
>
>  table.remove(tbl, i)
>
> to 
>
> tbl[i] = nil

But why can I do it for the top level table and not inner ones ?

xtbl = {
[1] = { "A" },
[2.5] = { "A", "B" },
[.5] = { "A" },
[5] = { "A", "B", "C" }
}

function dump(tbl)
    for i,f in pairs(tbl) do
        print(i, #f, f)

        for k,v in ipairs(f) do
            print('  ---', k, v)
        end
    end
end

function remove(tbl, func)
    for i, f in pairs( tbl ) do
        for k,v in ipairs(f) do
            if v == func then
                f[k] = nil
--                table.remove(f, k)
            end
        end
        if #f == 0 then
print('** remove', i)
            tbl[i] = nil
--            table.remove(tbl, i)
        end
    end
end

dump(xtbl)
remove(xtbl, 'A')

print("Resultat")
dump(xtbl)


1    1    table: 0x7bf4a8
  ---    1    A
5    3    table: 0x7c00b0
  ---    1    A
  ---    2    B
  ---    3    C
2.5    2    table: 0x7bf3c8
  ---    1    A
  ---    2    B
0.5    1    table: 0x7bf1d0
  ---    1    A
** remove    1
** remove    0.5
Resultat
5    3    table: 0x7c00b0
2.5    2    table: 0x7bf3c8

As you can see, I can't walk against inner ones :(

Reply | Threaded
Open this post in threaded view
|

Re: Table.remove() issue with the last element

Doug Currie
Laurent,

Don't replace table.remove(f, k), it's ok.

table.remove is meant to be used with tables with "valid indices." Your top-level table has "holes" and non-integer keys, whereas your deeper tables have "valid indices."

The other issue is that you are modifying tables while you are iterating over them. The combination of table.remove for a "list" iterated over with ipairs, and setting to nil with pairs seems to be ok, but not other combinations.

ipairs, remove with table.remove
pairs, remove with t[k] = nil

e


On Mon, Jun 20, 2016 at 6:07 PM, Laurent FAILLIE <[hidden email]> wrote:
Le Mardi 21 juin 2016 0h00, Doug Currie <[hidden email]> a écrit :



> You should change
>
>  table.remove(tbl, i)
>
> to 
>
> tbl[i] = nil

But why can I do it for the top level table and not inner ones ?

xtbl = {
[1] = { "A" },
[2.5] = { "A", "B" },
[.5] = { "A" },
[5] = { "A", "B", "C" }
}

function dump(tbl)
    for i,f in pairs(tbl) do
        print(i, #f, f)

        for k,v in ipairs(f) do
            print('  ---', k, v)
        end
    end
end

function remove(tbl, func)
    for i, f in pairs( tbl ) do
        for k,v in ipairs(f) do
            if v == func then
                f[k] = nil
--                table.remove(f, k)
            end
        end
        if #f == 0 then
print('** remove', i)
            tbl[i] = nil
--            table.remove(tbl, i)
        end
    end
end

dump(xtbl)
remove(xtbl, 'A')

print("Resultat")
dump(xtbl)


1    1    table: 0x7bf4a8
  ---    1    A
5    3    table: 0x7c00b0
  ---    1    A
  ---    2    B
  ---    3    C
2.5    2    table: 0x7bf3c8
  ---    1    A
  ---    2    B
0.5    1    table: 0x7bf1d0
  ---    1    A
** remove    1
** remove    0.5
Resultat
5    3    table: 0x7c00b0
2.5    2    table: 0x7bf3c8

As you can see, I can't walk against inner ones :(


Reply | Threaded
Open this post in threaded view
|

Re: Table.remove() issue with the last element

Doug Currie
BTW, see


for the restriction on modifying tables while traversing them with pairs.

e


On Mon, Jun 20, 2016 at 6:17 PM, Doug Currie <[hidden email]> wrote:
Laurent,

Don't replace table.remove(f, k), it's ok.

table.remove is meant to be used with tables with "valid indices." Your top-level table has "holes" and non-integer keys, whereas your deeper tables have "valid indices."

The other issue is that you are modifying tables while you are iterating over them. The combination of table.remove for a "list" iterated over with ipairs, and setting to nil with pairs seems to be ok, but not other combinations.

ipairs, remove with table.remove
pairs, remove with t[k] = nil

e


On Mon, Jun 20, 2016 at 6:07 PM, Laurent FAILLIE <[hidden email]> wrote:
Le Mardi 21 juin 2016 0h00, Doug Currie <[hidden email]> a écrit :



> You should change
>
>  table.remove(tbl, i)
>
> to 
>
> tbl[i] = nil

But why can I do it for the top level table and not inner ones ?

xtbl = {
[1] = { "A" },
[2.5] = { "A", "B" },
[.5] = { "A" },
[5] = { "A", "B", "C" }
}

function dump(tbl)
    for i,f in pairs(tbl) do
        print(i, #f, f)

        for k,v in ipairs(f) do
            print('  ---', k, v)
        end
    end
end

function remove(tbl, func)
    for i, f in pairs( tbl ) do
        for k,v in ipairs(f) do
            if v == func then
                f[k] = nil
--                table.remove(f, k)
            end
        end
        if #f == 0 then
print('** remove', i)
            tbl[i] = nil
--            table.remove(tbl, i)
        end
    end
end

dump(xtbl)
remove(xtbl, 'A')

print("Resultat")
dump(xtbl)


1    1    table: 0x7bf4a8
  ---    1    A
5    3    table: 0x7c00b0
  ---    1    A
  ---    2    B
  ---    3    C
2.5    2    table: 0x7bf3c8
  ---    1    A
  ---    2    B
0.5    1    table: 0x7bf1d0
  ---    1    A
** remove    1
** remove    0.5
Resultat
5    3    table: 0x7c00b0
2.5    2    table: 0x7bf3c8

As you can see, I can't walk against inner ones :(



Reply | Threaded
Open this post in threaded view
|

Re: Table.remove() issue with the last element

Laurent FAILLIE
In reply to this post by Doug Currie
ok, very clear : thanks for the explanation.

Bye

Laurent


Le Mardi 21 juin 2016 0h17, Doug Currie <[hidden email]> a écrit :


Laurent,

Don't replace table.remove(f, k), it's ok.

table.remove is meant to be used with tables with "valid indices." Your top-level table has "holes" and non-integer keys, whereas your deeper tables have "valid indices."

The other issue is that you are modifying tables while you are iterating over them. The combination of table.remove for a "list" iterated over with ipairs, and setting to nil with pairs seems to be ok, but not other combinations.

ipairs, remove with table.remove
pairs, remove with t[k] = nil

e


On Mon, Jun 20, 2016 at 6:07 PM, Laurent FAILLIE <[hidden email]> wrote:
Le Mardi 21 juin 2016 0h00, Doug Currie <[hidden email]> a écrit :



> You should change
>
>  table.remove(tbl, i)
>
> to 
>
> tbl[i] = nil

But why can I do it for the top level table and not inner ones ?

xtbl = {
[1] = { "A" },
[2.5] = { "A", "B" },
[.5] = { "A" },
[5] = { "A", "B", "C" }
}

function dump(tbl)
    for i,f in pairs(tbl) do
        print(i, #f, f)

        for k,v in ipairs(f) do
            print('  ---', k, v)
        end
    end
end

function remove(tbl, func)
    for i, f in pairs( tbl ) do
        for k,v in ipairs(f) do
            if v == func then
                f[k] = nil
--                table.remove(f, k)
            end
        end
        if #f == 0 then
print('** remove', i)
            tbl[i] = nil
--            table.remove(tbl, i)
        end
    end
end

dump(xtbl)
remove(xtbl, 'A')

print("Resultat")
dump(xtbl)


1    1    table: 0x7bf4a8
  ---    1    A
5    3    table: 0x7c00b0
  ---    1    A
  ---    2    B
  ---    3    C
2.5    2    table: 0x7bf3c8
  ---    1    A
  ---    2    B
0.5    1    table: 0x7bf1d0
  ---    1    A
** remove    1
** remove    0.5
Resultat
5    3    table: 0x7c00b0
2.5    2    table: 0x7bf3c8

As you can see, I can't walk against inner ones :(