Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
dan19
Binge Watcher

Abnormal issues with pushing data into an array

Jump to solution
sub addToList()

  matched = false
  countIndex = 0
  if m.global.watchList.Count() > 0
m.movieArray = m.global.watchList for each item in m.global.watchList if item.TITLE = m.selectedMovie.TITLE m.movieArray.delete(countIndex) m.global.watchList = m.movieArray matched = true else m.movieArray.push(m.selectedMovie) m.global.watchList = m.movieArray matched = false end if if matched then EXIT FOR countIndex = countIndex + 1 end for else m.movieArray.push(m.selectedMovie) m.global.watchList = m.movieArray end if end sub

I am practicing and simulating an actual watchlist array. The issue with the code here is; after adding two movies to the watchList (which works fine), when I add a third one, it adds it twice, and when I add a fourth one, it adds it four times, and so on.

What am I doing wrong with the logic?

Thanks.

0 Kudos
1 Solution

Accepted Solutions
renojim
Community Streaming Expert

Re: Abnormal issues with pushing data into an array

Jump to solution

Mixing "for each" and indices is a bad idea, but that's only part of the problem.  You're going to be pushing something every time the title doesn't match as you go through the loop.  If I'm following what you're trying to do you should do something like:

for i = 0 to m.global.watchList.Count() - 1
   if m.global.watchList[i].title = m.selectedMovie.TITLE then
      m.global.watchList.delete(i)
      exit for
   end if
end for
if i = m.global.watchList.Count() then m.global.watchList.Push(m.selectedMovie)

You could also use a matched flag, but if i is past the end of the watchList at the end of the for loop then it wasn't matched.

A note about your code:  using m.movieArray isn't really accomplishing anything.  Setting it equal to m.global.watchList doesn't create a copy of it, just another reference to the same data.  Take this example:

x = [1,2,3]
y = x
y.delete(1)
print x
print y

It will give:

<Component: roArray> =
[
    1
    3
]
<Component: roArray> =
[
    1
    3
]
Roku Community Streaming Expert

Help others find this answer and click "Accept as Solution."
If you appreciate my answer, maybe give me a Kudo.

I am not a Roku employee.

View solution in original post

5 REPLIES 5
renojim
Community Streaming Expert

Re: Abnormal issues with pushing data into an array

Jump to solution

Mixing "for each" and indices is a bad idea, but that's only part of the problem.  You're going to be pushing something every time the title doesn't match as you go through the loop.  If I'm following what you're trying to do you should do something like:

for i = 0 to m.global.watchList.Count() - 1
   if m.global.watchList[i].title = m.selectedMovie.TITLE then
      m.global.watchList.delete(i)
      exit for
   end if
end for
if i = m.global.watchList.Count() then m.global.watchList.Push(m.selectedMovie)

You could also use a matched flag, but if i is past the end of the watchList at the end of the for loop then it wasn't matched.

A note about your code:  using m.movieArray isn't really accomplishing anything.  Setting it equal to m.global.watchList doesn't create a copy of it, just another reference to the same data.  Take this example:

x = [1,2,3]
y = x
y.delete(1)
print x
print y

It will give:

<Component: roArray> =
[
    1
    3
]
<Component: roArray> =
[
    1
    3
]
Roku Community Streaming Expert

Help others find this answer and click "Accept as Solution."
If you appreciate my answer, maybe give me a Kudo.

I am not a Roku employee.
dan19
Binge Watcher

Re: Abnormal issues with pushing data into an array

Jump to solution

@renojim wrote:

Mixing "for each" and indices is a bad idea, but that's only part of the problem.  You're going to be pushing something every time the title doesn't match as you go through the loop.  If I'm following what you're trying to do you should do something like:

for i = 0 to m.global.watchList.Count() - 1
   if m.global.watchList[i].title = m.selectedMovie.TITLE then
      m.global.watchList.delete(i)
      exit for
   end if
end for
if i = m.global.watchList.Count() then m.global.watchList.Push(m.selectedMovie)

You could also use a matched flag, but if i is past the end of the watchList at the end of the for loop then it wasn't matched.

A note about your code:  using m.movieArray isn't really accomplishing anything.  Setting it equal to m.global.watchList doesn't create a copy of it, just another reference to the same data.  Take this example:

x = [1,2,3]
y = x
y.delete(1)
print x
print y

It will give:

<Component: roArray> =
[
    1
    3
]
<Component: roArray> =
[
    1
    3
]

Thanks for the explanation. I have tried pushing directly to global variables, but for some reason, it doesn't work. I never thought about the for loop style. I am still trying to figure out what and what I can do with brightscript. And thanks for pointing out the issue with assigning the value of the global array to the movieArray. I'll check this out and get back to you.

P.S: for the line coloured in your code, will "i" work, since it is outside the for loop? I see it was initialized with the for loop.

Thanks a lot!

0 Kudos
renojim
Community Streaming Expert

Re: Abnormal issues with pushing data into an array

Jump to solution

I don't know why pushing on a global variable wouldn't work.  Perhaps there's something else going on.

i will have a value outside the for loop.  It will either be the value it had when the loop hit the exit statement or one past the end of the loop (e.g., for i = 1 to 3 : end for, i will be 4 after executing this nothing loop). i doesn't go out of scope.

When it comes to BrightScript, print is your best friend and it's easy to get tripped up with almost everything being a reference.

Roku Community Streaming Expert

Help others find this answer and click "Accept as Solution."
If you appreciate my answer, maybe give me a Kudo.

I am not a Roku employee.
dan19
Binge Watcher

Re: Abnormal issues with pushing data into an array

Jump to solution

@renojim wrote:

I don't know why pushing on a global variable wouldn't work.  Perhaps there's something else going on.

i will have a value outside the for loop.  It will either be the value it had when the loop hit the exit statement or one past the end of the loop (e.g., for i = 1 to 3 : end for, i will be 4 after executing this nothing loop). i doesn't go out of scope.

When it comes to BrightScript, print is your best friend and it's easy to get tripped up with almost everything being a reference.


Thanks buddy. I'll give this a bunch of tries, and get back to you.

0 Kudos
sanity-check
Roku Guru

Re: Abnormal issues with pushing data into an array

Jump to solution
  ''' add a field
  m.global.addField("test", "array", false)
  m.global.test = ["foo", "bar"]
  ?formatJson(m.global.test) ''' ["foo","bar"]
  ''' did it work? yep

  ''' can we add an element like this?
  m.global.test.push("zzz")
  ?formatJson(m.global.test) ''' ["foo","bar"]
  ''' nope... why not?

  ''' what about this?
  m.global.test[0] = "zzz"
  ?formatJson(m.global.test) ''' ["foo","bar"]
  ''' still no

  ''' let's pull it into a local var
  temp = m.global.test 
  temp.push("zzz")
  ?formatJson(temp) ''' ["foo","bar","zzz"]
  ''' ok, great - not going mad.. so this should have a zzz in..
  ?formatJson(m.global.test) ''' ["foo","bar"]
  ''' ...but it doesn't

  ''' Soo.. whenever we access m.global.test it's returning
  ''' a *copy* not a reference. and changing the copy does not
  ''' change m.global.test
  m.global.test = temp
  ?formatJson(m.global.test) ''' ["foo","bar","zzz"]
  ''' great, we finally manage to change our array! but was that
  ''' assignment a copy or a ref?
  temp.push("!!!")
  ?formatJson(m.global.test) ''' ["foo","bar","zzz"]
  ''' no "!!!" - so assigning is a copy too

  ''' what about nested references? let's find out
  temp.push(["a","b"])
  m.global.test = temp
  ?formatJson(m.global.test) ''' ["foo","bar","zzz","!!!",["a","b"]]
  temp[4][0] = "hi"
  ?formatJson(temp) ''' ["foo","bar","zzz","!!!",["hi","b"]]
  ?formatJson(m.global.test) ''' ["foo","bar","zzz","!!!",["a","b"]]
  ''' no references kept there either - so that assignment is
  ''' doing a *deep* copy

  ''' clearly that's going to get expensive with big objects, what
  ''' can we do instead?
  temp2 = createObject("roSgNode", "node")
  m.global.addField("test2", "node", false)
  m.global.test2 = temp2
  foo = createObject("roSgNode", "node")
  foo.id = "foo"
  bar = createObject("roSgNode", "node")
  bar.id = "bar"
  temp2.appendChild(foo)
  temp2.appendChild(bar)
  ''' we've added children to temp2 *after* assigning it  
  ''' to m.global.test2.. did they appear?
  ?m.global.test2.getChild(0).id ''' foo
  ?m.global.test2.getChild(1).id ''' bar
  ''' ...yes! so if we use scenegraph nodes we can actually
  ''' deal with references instead of values
  xxx = createObject("roSgNode", "node")
  xxx.id = "xxx"
  m.global.test2.appendChild(xxx)
  ?m.global.test2.getChild(2).id ''' xxx
  ''' great - it works directly too. 
  ''' it's just a shame it's a node, not a string!
0 Kudos