mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-22 22:12:28 -05:00
Implement 'get item # of (thing) in (list)'
This commit is contained in:
parent
2d9bd92140
commit
b861c78086
2 changed files with 78 additions and 0 deletions
|
@ -24,6 +24,7 @@ class Scratch3DataBlocks {
|
|||
data_insertatlist: this.insertAtList,
|
||||
data_replaceitemoflist: this.replaceItemOfList,
|
||||
data_itemoflist: this.getItemOfList,
|
||||
data_itemnumoflist: this.getItemNumOfList,
|
||||
data_lengthoflist: this.lengthOfList,
|
||||
data_listcontainsitem: this.listContainsItem
|
||||
};
|
||||
|
@ -122,6 +123,34 @@ class Scratch3DataBlocks {
|
|||
return list.value[index - 1];
|
||||
}
|
||||
|
||||
getItemNumOfList (args, util) {
|
||||
const item = args.ITEM;
|
||||
const list = util.target.lookupOrCreateList(
|
||||
args.LIST.id, args.LIST.name);
|
||||
|
||||
// Go through the list items one-by-one using Cast.compare. This is for
|
||||
// cases like checking if 123 is contained in a list [4, 7, '123'] --
|
||||
// Scratch considers 123 and '123' to be equal.
|
||||
for (let i = 0; i < list.value.length; i++) {
|
||||
if (Cast.compare(list.value[i], item) === 0) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// We don't bother using .indexOf() at all, because it would end up with
|
||||
// edge cases such as the index of '123' in [4, 7, 123, '123', 9].
|
||||
// If we use indexOf(), this block would return 4 instead of 3, because
|
||||
// indexOf() sees the first occurence of the string 123 as the fourth
|
||||
// item in the list. With Scratch, this would be confusing -- after all,
|
||||
// '123' and 123 look the same, so one would expect the block to say
|
||||
// that the first occurrence of '123' (or 123) to be the third item.
|
||||
|
||||
// Default to 0 if there's no match. Since Scratch lists are 1-indexed,
|
||||
// we don't have to worry about this conflicting with the "this item is
|
||||
// the first value" number (in JS that is 0, but in Scratch it's 1).
|
||||
return 0;
|
||||
}
|
||||
|
||||
lengthOfList (args, util) {
|
||||
const list = util.target.lookupOrCreateList(
|
||||
args.LIST.id, args.LIST.name);
|
||||
|
|
49
test/unit/blocks_data.js
Normal file
49
test/unit/blocks_data.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
const test = require('tap').test;
|
||||
const Data = require('../../src/blocks/scratch3_data');
|
||||
|
||||
const blocks = new Data();
|
||||
|
||||
const lists = {};
|
||||
const util = {
|
||||
target: {
|
||||
lookupOrCreateList(id, name) {
|
||||
if (!(name in lists)) {
|
||||
lists[name] = {value: []};
|
||||
}
|
||||
return lists[name];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test('getItemNumOfList returns the index of an item (basic)', t => {
|
||||
lists.list = {value: ['apple', 'taco', 'burrito', 'extravaganza']};
|
||||
const args = {ITEM: 'burrito', LIST: {name: 'list'}};
|
||||
const index = blocks.getItemNumOfList(args, util);
|
||||
t.strictEqual(index, 3);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('getItemNumOfList returns 0 when an item is not found', t => {
|
||||
lists.list = {value: ['aaaaapple', 'burrito']};
|
||||
const args = {ITEM: 'jump', LIST: {name: 'list'}};
|
||||
const index = blocks.getItemNumOfList(args, util);
|
||||
t.strictEqual(index, 0);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('getItemNumOfList uses Scratch comparison', t => {
|
||||
lists.list = {value: ['jump', 'Jump', '123', 123, 800]};
|
||||
const args = {LIST: {name: 'list'}};
|
||||
|
||||
// Be case-insensitive:
|
||||
args.ITEM = 'Jump';
|
||||
t.strictEqual(blocks.getItemNumOfList(args, util), 1);
|
||||
|
||||
// Be type-insensitive:
|
||||
args.ITEM = 123;
|
||||
t.strictEqual(blocks.getItemNumOfList(args, util), 3);
|
||||
args.ITEM = '800';
|
||||
t.strictEqual(blocks.getItemNumOfList(args, util), 5);
|
||||
|
||||
t.end();
|
||||
});
|
Loading…
Reference in a new issue