Deleting an array entry at a specific index always deletes the last entry

Twine Version: 2.8.1.0, Sugarcube

Hi everyone - I’m making a game in which the player pulls a random painting from an array, then gets a random memory from an a mood-specific memory array based on the painting’s mood property. Example of one of those arrays:

<<set $joyMemoryBank to [
	{
    	id: 0,
        description: "first memory text goes here yada yada yada"
        },
        {
    	id: 1,
        description: "second memory text goes here yada yada yada"
        },
        {
    	id: 2,
        description: "third memory text goes here yada yada yada"
        }
]>>

The object’s properties are put in a temporary value and the description is printed, and then the game deletes the object from the memory array based on the id value. Or at least, it’s supposed to. My code is correctly figuring out which index to delete at, but no matter what I try, it just deletes the last object in the array. So, after printing the text of the temp variable’s description property, it doesn’t actually delete the memory I want and may repeat it later (plus, the final memory in the array will never get selected).

Here’s what I got, along with my debug text:

<<if $currentPaintingPull.mood is "joy">>
	<<set _currentMemory to either($joyMemoryBank)>>
   I should delete at index position _currentMemory.id.
    <<set $joyMemoryBank.deleteAt($joyMemoryBank.indexOf(_currentMemory.id))>>I deleted the memory from joyMemoryBank. It should no longer appear.
<</if>>

And then, no matter what the selection actually is, my $joyMemoryBank looks like this:

<<set $joyMemoryBank to [
	{
    	id: 0,
        description: "first memory text goes here yada yada yada"
        },
        {
    	id: 1,
        description: "second memory text goes here yada yada yada"
        }
]>>

Why is it doing this? :confused:

Hoping this doesn’t replicate any other questions - none of the other responses I read seemed right. Also hoping the answer isn’t contained in the last question I asked about this project, and I just couldn’t figure it out…

Hi,

Have you tried to delete a specific id from the array instead of using “either”?

<<if $currentPaintingPull.mood is "joy">>
	<<set _currentMemory to either(0)>> NOTE THE ZERO
   I should delete at index position _currentMemory.id.
    <<set $joyMemoryBank.deleteAt($joyMemoryBank.indexOf(_currentMemory.id))>>I deleted the memory from joyMemoryBank. It should no longer appear.
<</if>>

One problem is that you’re using <Array>.indexOf() incorrectly. It’s used when you have the actual value itself on hand—one of the generic objects in this case.

To search by some criteria—e.g., a property from your objects—instead, you should be using either <Array>.find() or <Array>.findIndex().

NOTE: I’m currently assuming that your examples refering to the objects’ .id property as an index is simple confusion. If that was actually your intention, then you’re going about this all sorts of wrongly.

 

<Array>.find() example

Note the use of <Array>.delete()> here, since the member itself is being returned.

<<if $currentPaintingPull.mood is "joy">>
	<<set _currentMemory to either($joyMemoryBank)>>
	I should delete the object with ID _currentMemory.id.
	<<run $joyMemoryBank.delete($joyMemoryBank.find(O => O.id === _currentMemory.id))>>
	I deleted the memory from joyMemoryBank. It should no longer appear.
<</if>>

<Array>.findIndex() example

<<if $currentPaintingPull.mood is "joy">>
	<<set _currentMemory to either($joyMemoryBank)>>
	I should delete the object with ID _currentMemory.id.
	<<run $joyMemoryBank.deleteAt($joyMemoryBank.findIndex(O => O.id === _currentMemory.id))>>
	I deleted the memory from joyMemoryBank. It should no longer appear.
<</if>>
2 Likes

Looks like it’s your indexOf call: you’re passing it the id, which is a number. But the $joyMemoryBank holds objects, not numbers. So indexOf won’t find the number, and it’ll return -1, and then you’ll always be deleting the -1 entry (which is at the end).

1 Like

It may be a silly question, but why do you need your array to be an array of objects? Right now your objects are

  • A key
  • A text

However each array comes by itself with its very own key. So you could write;

<<set $joyMemoryBank to ["first memory text goes here yada yada yada","second memory text goes here yada yada yada","third memory text goes here yada yada yada"]>>

Then you’d have $joyMemoryBank[0],$joyMemoryBank[1] and $joyMemoryBank[2] to recall these memories.

The next step would be to conjure one of those:

 <<if $currentPaintingPull.mood is "joy">>
	<<set _currentMemory to $joyMemoryBank.pluck()>>
 <</if>>

The pluck() method is exactly doing what you’re doing with a lengthier code: randomly taking an array member and deleting this member from the array.

1 Like

I tried this (exactly as you described, zero and everything!) and got the following error:

Error: <<set>>: bad evaluation: State.temporary.currentMemory.description is undefined.

Correct me if I’m wrong: once I place an object into _currentMemory, the random object plucked would not retain its index from the original array…would it? Wouldn’t the index just be 0?

Otherwise I agree, the code is redundant and I shouldn’t do it this way!

Your first suggestion worked perfectly, thank you!

And I was referring to the id property because I assumed that, if I’m selecting an object from an array and putting it into a temp variable, the index of the temp variable just defaults to 0, because it’s the only object in there (like I said in my reply to souppilouliouma). Thus the id property to preserve the original index #. But this could be wrong and it does preserve the index from $joyMemoryBank. I’d love to know either way!

1 Like

With what I propose _currentMemory is not an array, it’s a simple character variable. Then there’s no attached index. Also each time something is plucked from the array, all members initially after the one plucked get a new index, so the index numbers staysa list of consecuvie numbers starting with zero.
Do you need the index associated with each memory at some point of your code?