App Inventor 2 列表操作进阶教程 - 去重/排序/查找

« 返回首页

概述

列表(List)是App Inventor 2中最常用的数据结构。本文介绍列表的高级操作技巧,解决用户常见需求:

  • 判断列表中有没有重复项
  • 列表去重
  • 列表排序
  • 列表查找和过滤
  • 列表交叉/差集操作

列表基础回顾

常用列表积木块

操作 积木块 说明
创建 make a list 创建列表
添加 add items to list 末尾添加元素
读取 select list item 按索引读取
长度 length of list 获取元素数量
是否在列表 is in list? 判断元素是否存在
索引 index in list 获取元素的索引
删除 remove list item 按索引删除
替换 replace list item 按索引替换

判断列表中有没有重复项

方法一:逐个比较

function hasDuplicate(list) {
  var result = False
  var i = 1
  while i <= lengthOfList(list) - 1 {
    var j = i + 1
    while j <= lengthOfList(list) {
      if selectListItem(list, i) == selectListItem(list, j) {
        result = True
        j = lengthOfList(list) + 1 // break
        i = lengthOfList(list) + 1 // break
      } else {
        j = j + 1
      }
    }
    i = i + 1
  }
  return result
}

方法二:利用字典去重后比较长度

function hasDuplicateByDict(list) {
  var uniqueList = uniqueValues(list)
  var result = False
  if lengthOfList(uniqueList) < lengthOfList(list) {
    result = True
  } else {
    result = False
  }
  return result
}

使用示例

when Button1.Click() {
  var myList = createList("苹果", "香蕉", "橙子", "香蕉", "葡萄")
  if hasDuplicate(myList) {
    Label1.Text = "⚠️ 列表中有重复项"
  } else {
    Label1.Text = "✅ 列表中没有重复项"
  }
}

列表去重

方法一:利用字典键去重(推荐)

字典的键是唯一的,可以巧妙地用来去重:

function uniqueValues(list) {
  var uniqueList = createList()
  var i = 1
  while i <= lengthOfList(list) {
    var currentItem = selectListItem(list, i)
    if not(isItemInList(currentItem, uniqueList)) {
      addItemsToList(uniqueList, currentItem)
    }
    i = i + 1
  }
  return uniqueList
}

方法二:保持顺序的去重

function uniqueValuesOrdered(list) {
  var seen = createList()
  var resultList = createList()
  var i = 1
  while i <= lengthOfList(list) {
    var currentItem = selectListItem(list, i)
    if not(isItemInList(currentItem, seen)) {
      addItemsToList(seen, currentItem)
      addItemsToList(resultList, currentItem)
    }
    i = i + 1
  }
  return resultList
}

获取重复项列表

function getDuplicates(list) {
  var duplicates = createList()
  var seen = createList()
  var i = 1
  while i <= lengthOfList(list) {
    var currentItem = selectListItem(list, i)
    if isItemInList(currentItem, seen) {
      if not(isItemInList(currentItem, duplicates)) {
        addItemsToList(duplicates, currentItem)
      }
    } else {
      addItemsToList(seen, currentItem)
    }
    i = i + 1
  }
  return duplicates
}

统计每个元素出现次数

function countFrequencies(list) {
  var frequencies = createDictionary()
  var i = 1
  while i <= lengthOfList(list) {
    var currentItem = selectListItem(list, i)
    if isDictionaryKey(frequencies, currentItem) {
      var currentCount = getDictionaryValue(frequencies, currentItem)
      setDictionaryValue(frequencies, currentItem, currentCount + 1)
    } else {
      setDictionaryValue(frequencies, currentItem, 1)
    }
    i = i + 1
  }
  return frequencies
}

列表排序

冒泡排序

function bubbleSort(list) {
  var sortedList = copyList(list)
  var n = lengthOfList(sortedList)
  var i = 1
  while i <= n - 1 {
    var j = 1
    while j <= n - i {
      if selectListItem(sortedList, j) > selectListItem(sortedList, j + 1) {
        // 交换
        var temp = selectListItem(sortedList, j)
        replaceListItem(sortedList, j, selectListItem(sortedList, j + 1))
        replaceListItem(sortedList, j + 1, temp)
      }
      j = j + 1
    }
    i = i + 1
  }
  return sortedList
}

数字排序(从小到大)

function numericSort(list) {
  var sortedList = copyList(list)
  var n = lengthOfList(sortedList)
  var i = 1
  while i <= n - 1 {
    var j = 1
    while j <= n - i {
      var a = selectListItem(sortedList, j)
      var b = selectListItem(sortedList, j + 1)
      if a > b {
        var temp = selectListItem(sortedList, j)
        replaceListItem(sortedList, j, selectListItem(sortedList, j + 1))
        replaceListItem(sortedList, j + 1, temp)
      }
      j = j + 1
    }
    i = i + 1
  }
  return sortedList
}

列表查找和过滤

查找所有匹配项

function findAll(list, target) {
  var result = createList()
  var i = 1
  while i <= lengthOfList(list) {
    if selectListItem(list, i) == target {
      addItemsToList(result, i)
    }
    i = i + 1
  }
  return result
}

按条件过滤

function filterGreaterThan(list, threshold) {
  var result = createList()
  var i = 1
  while i <= lengthOfList(list) {
    var val = selectListItem(list, i)
    if val > threshold {
      addItemsToList(result, selectListItem(list, i))
    }
    i = i + 1
  }
  return result
}

模糊搜索

function fuzzySearch(list, keyword) {
  var result = createList()
  var i = 1
  while i <= lengthOfList(list) {
    var currentItem = selectListItem(list, i)
    if containsText(currentItem, keyword) {
      addItemsToList(result, currentItem)
    }
    i = i + 1
  }
  return result
}

列表集合操作

交集(两个列表共同元素)

function intersectLists(listA, listB) {
  var result = createList()
  var i = 1
  while i <= lengthOfList(listA) {
    if isItemInList(selectListItem(listA, i), listB) {
      addItemsToList(result, selectListItem(listA, i))
    }
    i = i + 1
  }
  return uniqueValues(result)
}

差集(在A但不在B中)

function listDifference(listA, listB) {
  var result = createList()
  var i = 1
  while i <= lengthOfList(listA) {
    if not(isItemInList(selectListItem(listA, i), listB)) {
      addItemsToList(result, selectListItem(listA, i))
    }
    i = i + 1
  }
  return result
}

合并去重

function mergeUnique(listA, listB) {
  var merged = copyList(listA)
  appendListToList(merged, listB)
  return uniqueValues(merged)
}

实用工具函数

列表转逗号分隔文本

function listToText(list, sep) {
  var result = ""
  var i = 1
  while i <= lengthOfList(list) {
    if i == 1 {
      result = selectListItem(list, i)
    } else {
      result = join(result, sep, selectListItem(list, i))
    }
    i = i + 1
  }
  return result
}

列表最大值/最小值

function listMax(list) {
  var maxVal = selectListItem(list, 1)
  var i = 2
  while i <= lengthOfList(list) {
    var currentVal = selectListItem(list, i)
    if currentVal > maxVal {
      maxVal = currentVal
    }
    i = i + 1
  }
  return maxVal
}

常见问题

Q1: is in list 区分大小写吗?

是的,is in list 精确匹配,区分大小写。如果需要不区分大小写的查找:

function containsCaseInsensitive(list, target) {
  var found = False
  var i = 1
  while i <= lengthOfList(list) {
    if downcase(selectListItem(list, i)) == downcase(target) {
      found = True
      i = lengthOfList(list) + 1 // break
    } else {
      i = i + 1
    }
  }
  return found
}

Q2: 如何随机打乱列表?

function randomShuffle(list) {
  var result = copyList(list)
  var i = lengthOfList(result)
  while i > 1 {
    var j = randomInteger(1, i)
    var temp = selectListItem(result, i)
    replaceListItem(result, i, selectListItem(result, j))
    replaceListItem(result, j, temp)
    i = i - 1
  }
  return result
}

总结

操作 时间复杂度 适用场景
判断重复 O(n²) 或 O(n) 数据验证
去重 O(n²) 数据清洗
排序 O(n²) 显示排序
查找 O(n) 搜索功能
过滤 O(n) 数据筛选
文档反馈