noob 'why doesn't this work' question

V

Vincent Angeloni

Hi and greetings to all group members!

I'm a new Ruby user with a background in Applescript, Hypertalk
(Supercard), and a little Unix. I was intrigued by Matt Neuburg's
article about Applescript and Ruby, and that's what got me reading some
intro books on Ruby. I just bought Textmate and I am lovin' it!

Anyway, I am wondering why this seemingly simple script fails:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.each {|x| sizeList.delete_at(x)}

what I want to happen is that sizelist gets deleted at the positions
specified in countArray, but the result I am getting is:

0
1
2
4
6

and the expected result should be 0,1,2,5, right?
What gives?

TIA,
vince

Mac OS X 10.5.2, G5 Quad, Textmate editor, ruby 1.86
 
J

Jesús Gabriel y Galán

Hi and greetings to all group members!

I'm a new Ruby user with a background in Applescript, Hypertalk
(Supercard), and a little Unix. I was intrigued by Matt Neuburg's
article about Applescript and Ruby, and that's what got me reading some
intro books on Ruby. I just bought Textmate and I am lovin' it!

Anyway, I am wondering why this seemingly simple script fails:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.each {|x| sizeList.delete_at(x)}

what I want to happen is that sizelist gets deleted at the positions
specified in countArray, but the result I am getting is:

0
1
2
4
6

and the expected result should be 0,1,2,5, right?
What gives?

Every time you delete an element, all the values to the right are
shifted one position. What you are doing essentially is:

irb(main):001:0> a = [0,1,2,3,4,5,6]
=> [0, 1, 2, 3, 4, 5, 6]
irb(main):002:0> a.delete_at(3)
=> 3
irb(main):003:0> a
=> [0, 1, 2, 4, 5, 6]
irb(main):004:0> a.delete_at(4)
=> 5
irb(main):005:0> a
=> [0, 1, 2, 4, 6]
irb(main):006:0> a.delete_at(6)
=> nil
irb(main):007:0> a
=> [0, 1, 2, 4, 6]

After the first delete_at, the elements 4,5 and 6 are shifted to fill the space
of the deleted element. So now, the element at index 4 is not the 4, it's the 5.
After those two deletions, the array no longer holds an element with index 6, so
the last deletion does nothing.

Hope this helps,

Jesus.
 
J

Joachim Glauche

Vincent said:
Hi and greetings to all group members!

I'm a new Ruby user with a background in Applescript, Hypertalk
(Supercard), and a little Unix. I was intrigued by Matt Neuburg's
article about Applescript and Ruby, and that's what got me reading some
intro books on Ruby. I just bought Textmate and I am lovin' it!

Anyway, I am wondering why this seemingly simple script fails:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.each {|x| sizeList.delete_at(x)}
and the expected result should be 0,1,2,5, right?
What gives?

Start counting at 0
 
L

Luis Lavena

Hi and greetings to all group members!

I'm a new Ruby user with a background in Applescript, Hypertalk
(Supercard), and a little Unix. I was intrigued by Matt Neuburg's
article about Applescript and Ruby, and that's what got me reading some
intro books on Ruby. I just bought Textmate and I am lovin' it!

Anyway, I am wondering why this seemingly simple script fails:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.each {|x| sizeList.delete_at(x)}

what I want to happen is that sizelist gets deleted at the positions
specified in countArray, but the result I am getting is:

0
1
2
4
6

and the expected result should be 0,1,2,5, right?
What gives?

Actually no, when you #delete_at one element from an array, the
indexes of it get altered too:

You can interpret what is doing #each on countarray:

irb(main):001:0> sizeList = [0,1,2,3,4,5,6]
=> [0, 1, 2, 3, 4, 5, 6]
irb(main):002:0> sizeList.delete_at(3)
=> 3
irb(main):003:0> sizeList.delete_at(4)
=> 5
irb(main):004:0> sizeList.delete_at(6)
=> nil

So, each time you iterate over countarray and remove the indicated
position, sizeList gets updated, and thus, the next items in the
countarray no longer reference your expected positions.

Errr, sound complicated my explanation, anyone with a better written
one? :)

HTH,
 
V

Vincent Angeloni

Luis said:
countarray = [3,4,6]

and the expected result should be 0,1,2,5, right?
What gives?

Actually no, when you #delete_at one element from an array, the
indexes of it get altered too:

You can interpret what is doing #each on countarray:

irb(main):001:0> sizeList = [0,1,2,3,4,5,6]
=> [0, 1, 2, 3, 4, 5, 6]
irb(main):002:0> sizeList.delete_at(3)
=> 3
irb(main):003:0> sizeList.delete_at(4)
=> 5
irb(main):004:0> sizeList.delete_at(6)
=> nil

So, each time you iterate over countarray and remove the indicated
position, sizeList gets updated, and thus, the next items in the
countarray no longer reference your expected positions.

Errr, sound complicated my explanation, anyone with a better written
one? :)

HTH,

Ah, yes. I knew it was something simple.
I'll just sort countarray so that the highest index value is first, and
perhaps that will take care of the problem!
Thank you.

vince
 
K

Karl von Laudermann

Ah, yes. I knew it was something simple.
I'll just sort countarray so that the highest index value is first, and
perhaps that will take care of the problem!
Thank you.

Another approach would be: instead of deleting each item, put nil at
each specified array index. Then, after you're done iterating, delete
all the nils using Array#compact!, like so:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.each {|x| sizeList[x] = nil}
sizeList.compact!
 
R

Robert Klemme

Ah, yes. I knew it was something simple.
I'll just sort countarray so that the highest index value is first, and
perhaps that will take care of the problem!
Thank you.

Another approach would be: instead of deleting each item, put nil at
each specified array index. Then, after you're done iterating, delete
all the nils using Array#compact!, like so:

sizeList = [0,1,2,3,4,5,6]

Btw, the conventional way in Ruby is to use "size_list" instead of
CamelCase for method and variable names.
countarray = [3,4,6]
countarray.each {|x| sizeList[x] = nil}
sizeList.compact!

Yet another alternative is to delete based on /criteria/ and not /position/.

In this case that could be

# note, the array in the block is not the original
# array but contains entries to be deleted - it's
# only accidentally the same because of the way that
# size_list is built.
size_list.delete_if {|x| [3,4,6].include? x}

Or any other criterium.

Kind regards

robert
 
M

Marc Heiler

I'm not entirely sure what you're trying to accomplish anyway

I guess he is starting to _learn_ which could explain what he
is wanting to accomplish so examples don't necessarily need to
make much sense and his head will slowly fill up with
101 ways to achieve what he wants to have ;-)
 
V

Vincent Angeloni

Marc said:
I guess he is starting to _learn_ which could explain what he
is wanting to accomplish so examples don't necessarily need to
make much sense and his head will slowly fill up with
101 ways to achieve what he wants to have ;-)

Basically, I'm trying to get a list of files/folders along with
a separate list of the sizes of said files. The array deletions
I asked about would be the deletion of files enclosed in folders
from the original file list and using the position of the items
in the file list to delete the corresponding array position in
the separate size list of those files.

And thanks to everyone who responded. 101 ways to do this would
be great, but I'll settle for 4 or 5. ;-)

This has been very helpful.

vince
 
P

Peña, Botp

RnJvbTogbGlzdC1ib3VuY2VAZXhhbXBsZS5jb20gDQojIEFuZCB0aGFua3MgdG8gZXZlcnlvbmUg
d2hvIHJlc3BvbmRlZC4gMTAxIHdheXMgdG8gZG8gdGhpcyB3b3VsZA0KIyBiZSBncmVhdCwgYnV0
IEknbGwgc2V0dGxlIGZvciA0IG9yIDUuIDstKQ0KDQppIGhvcGUgdGhpcyBjYXRjaGVzIHVwIHRo
ZSA1dGggd2F5IDopDQoNCnJ1YnkxLjkgdGhvdWdoLA0KDQppcmIobWFpbik6MDA0OjA+IHNpemVM
aXN0Lmdyb3VwX2J5LndpdGhfaW5kZXh7fGUsaXwgY291bnRhcnJheS5pbmNsdWRlPyBpfQ0KPT4g
e2ZhbHNlPT5bMCwgMSwgMiwgNV0sIHRydWU9PlszLCA0LCA2XX0NCg0KZnIgaGVyZSB5b3UgY2Fu
IGdldCB3aGF0IGdldHMgZGVsZXRlZCwNCg0KaXJiKG1haW4pOjAxNjowPiBzaXplTGlzdC5ncm91
cF9ieS53aXRoX2luZGV4e3xlLGl8IGNvdW50YXJyYXkuaW5jbHVkZT8gaX1bdHJ1ZV0NCj0+IFsz
LCA0LCA2XQ0KDQphbmQgd2hhdCByZW1haW5zLA0KDQppcmIobWFpbik6MDE3OjA+IHNpemVMaXN0
Lmdyb3VwX2J5LndpdGhfaW5kZXh7fGUsaXwgY291bnRhcnJheS5pbmNsdWRlPyBpfVtmYWxzZV0N
Cj0+IFswLCAxLCAyLCA1XQ0KDQp0aGUgYmVhdXR5IGhlcmUgaXMgeW91IGNhbiBnbyBzbG93bHks
IGFuZCBwaWN0dXJlIG91dCBhbmQgY29tcGFyZSBpbiBhZHZhbmNlIHdoYXQgd2lsbCBiZSBkZWxl
dGVkIGFuZCB3aGF0IHdpbGwgcmVtYWluLi4uDQoNCmtpbmQgcmVnYXJkcyAtYm90cA0K
 
P

Paul

irb(main):001:0> a = [0,1,2,3,4,5,6]
=> [0, 1, 2, 3, 4, 5, 6]
irb(main):002:0> b = [3,4,6]
=> [3, 4, 6]
irb(main):003:0> c = a - b
=> [0, 1, 2, 5]
irb(main):004:0>
 
P

Peña, Botp

From: Paul [mailto:p[email protected]]=20
# irb(main):001:0> a =3D [0,1,2,3,4,5,6]
# =3D> [0, 1, 2, 3, 4, 5, 6]
# irb(main):002:0> b =3D [3,4,6]
# =3D> [3, 4, 6]
# irb(main):003:0> c =3D a - b
# =3D> [0, 1, 2, 5]

Hi Paul, the op meant that the array b contains indexes for a (and not =
contents as in your example)

kind regards -botp
 
P

Peña, Botp

RnJvbTogUGXDsWEsIEJvdHAgW21haWx0bzpib3RwQGRlbG1vbnRlLXBoaWwuY29tXSANCiMgaXJi
KG1haW4pOjAwNDowPiBzaXplTGlzdC5ncm91cF9ieS53aXRoX2luZGV4e3xlLGl8IA0KIyBjb3Vu
dGFycmF5LmluY2x1ZGU/IGl9DQojID0+IHtmYWxzZT0+WzAsIDEsIDIsIDVdLCB0cnVlPT5bMywg
NCwgNl19DQoNCjZ0aCB3YXkgOikNCg0KOjA+IHNpemVMaXN0LnZhbHVlc19hdCgqKDAuLnNpemVM
aXN0LnNpemUtMSkudG9fYS1jb3VudGFycmF5KQ0KPT4gWzAsIDEsIDIsIDVdDQoNCnRoaXMgb25l
IHBsYXlzIHcgdGhlIGluZGljZXMsIHRoZW4gdXNlcyB2YWx1ZXNfYXQgdG8gZ2V0IGJhY2sgdG8g
dGhlIGNvbnRlbnRzLg0KDQpraW5kIHJlZ2FyZHMgLWJvdHANCg==
 
J

Jesús Gabriel y Galán

Basically, I'm trying to get a list of files/folders along with
a separate list of the sizes of said files. The array deletions
I asked about would be the deletion of files enclosed in folders
from the original file list and using the position of the items
in the file list to delete the corresponding array position in
the separate size list of those files.

Another solution could be, instead of having 2 arrays, to have
a single array where each position contains all the info for
a file, maybe like an array or hash, and then delete based on
the size info. Example:

file_info = [["a.txt", 123], ["b.txt", 10000]]
file_info.delete_if {|x| x[1] > 1000}

will delete all entries whose size is bigger than 1000.

As a hash:

file_info = [{:name => "a.txt", :size => 123}, {:name => "b.txt",
:size => 10000}]
file_info.delete_if {|x| x[:size] > 1000}

or you could have a custom object if you need more complex modelling
of the file info.

Hope this helps,

Jesus.
 
R

Robin Pedersen

Hi and greetings to all group members!

I'm a new Ruby user with a background in Applescript, Hypertalk
(Supercard), and a little Unix. I was intrigued by Matt Neuburg's
article about Applescript and Ruby, and that's what got me reading some
intro books on Ruby. I just bought Textmate and I am lovin' it!

Anyway, I am wondering why this seemingly simple script fails:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.each {|x| sizeList.delete_at(x)}

what I want to happen is that sizelist gets deleted at the positions
specified in countArray, but the result I am getting is:

0
1
2
4
6

and the expected result should be 0,1,2,5, right?
What gives?

TIA,
vince

Mac OS X 10.5.2, G5 Quad, Textmate editor, ruby 1.86

What about this:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.sort.reverse.each {|x| sizeList.delete_at(x)}

Result: 0,1,2,5
 
S

Stephen Schor

[Note: parts of this message were removed to make it a legal post.]

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.each {|x| sizeList.delete_at(x)}

Let's look at what's going on inside your .each block.
The first iteration it will delete the sizeList[3]. ===> [0,1,2,4,5,6]
The second iteration it will delete sizeList[4] ===> [0,1,2,4,6]
The final iteration it will delete sizeList[6] ==> [0,1,2,4,6] #there
is no sizeList[6] - deleteAt returns nil.

Your indexs are changing each time you call delete_at.

-Stephen





Hi and greetings to all group members!

I'm a new Ruby user with a background in Applescript, Hypertalk
(Supercard), and a little Unix. I was intrigued by Matt Neuburg's
article about Applescript and Ruby, and that's what got me reading some
intro books on Ruby. I just bought Textmate and I am lovin' it!

Anyway, I am wondering why this seemingly simple script fails:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.each {|x| sizeList.delete_at(x)}

what I want to happen is that sizelist gets deleted at the positions
specified in countArray, but the result I am getting is:

0
1
2
4
6

and the expected result should be 0,1,2,5, right?
What gives?

TIA,
vince

Mac OS X 10.5.2, G5 Quad, Textmate editor, ruby 1.86

What about this:

sizeList = [0,1,2,3,4,5,6]
countarray = [3,4,6]
countarray.sort.reverse.each {|x| sizeList.delete_at(x)}

Result: 0,1,2,5
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top