优化:手机号匹配通讯录联系人算法改进 #580

This commit is contained in:
pppscn 2025-02-13 17:07:55 +08:00
parent 8b37862121
commit 992cabe323

View File

@ -31,6 +31,7 @@ import com.xuexiang.xutil.data.DateUtils
import com.xuexiang.xutil.resource.ResUtils.getString
import java.text.SimpleDateFormat
import java.util.Locale
import kotlin.math.min
@Suppress("DEPRECATION")
class PhoneUtils private constructor() {
@ -339,7 +340,7 @@ class PhoneUtils private constructor() {
//获取联系人列表
fun getContactInfoList(
limit: Int, offset: Int, phoneNumber: String?, name: String?
limit: Int, offset: Int, phoneNumber: String?, name: String?, isFuzzy: Boolean = true
): MutableList<ContactInfo> {
val contactInfoList: MutableList<ContactInfo> = mutableListOf()
@ -348,7 +349,11 @@ class PhoneUtils private constructor() {
val selectionArgs = ArrayList<String>()
if (!TextUtils.isEmpty(phoneNumber)) {
selection += " and replace(replace(" + ContactsContract.CommonDataKinds.Phone.NUMBER + ",' ',''),'-','') like ?"
selectionArgs.add("%$phoneNumber%")
if (isFuzzy) {
selectionArgs.add("%$phoneNumber%")
} else {
selectionArgs.add("%$phoneNumber")
}
}
if (!TextUtils.isEmpty(name)) {
selection += " and " + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " like ?"
@ -396,7 +401,61 @@ class PhoneUtils private constructor() {
fun getContactByNumber(phoneNumber: String?): MutableList<ContactInfo> {
val contactInfoList = mutableListOf<ContactInfo>()
if (TextUtils.isEmpty(phoneNumber)) return contactInfoList
return getContactInfoList(1, 0, phoneNumber, null)
// 去除国际区号、空格、括号、横线等字符
val normalizedInputNumber = if (phoneNumber!!.startsWith("+") && phoneNumber.length > 4) {
phoneNumber.substring(4).replace("[^0-9]".toRegex(), "")
} else {
phoneNumber.replace("[^0-9]".toRegex(), "")
}
contactInfoList.addAll(getContactInfoList(99, 0, normalizedInputNumber, null, false))
if (contactInfoList.isEmpty() || contactInfoList.size == 1) {
return contactInfoList
}
// 计算每个联系人的匹配长度和优先级
val scoredContacts = contactInfoList.map { contact ->
//去除空格、括号、横线等字符
val normalizedContactNumber = contact.phoneNumber.replace("[^0-9]".toRegex(), "")
val matchLength = calculateMatchLength(normalizedInputNumber, normalizedContactNumber)
// 优先级规则:
// 1. 完全匹配(输入手机号与联系人手机号完全一致):优先级 2
// 2. 匹配长度等于输入手机号长度:优先级 1
// 3. 其他情况:优先级 0
val priority = when {
normalizedInputNumber == normalizedContactNumber -> 2
matchLength == normalizedInputNumber.length -> 1
else -> 0
}
contact to Pair(matchLength, priority)
}.sortedWith(compareByDescending<Pair<ContactInfo, Pair<Int, Int>>> { it.second.first } // 按匹配长度降序
.thenByDescending { it.second.second }) // 按优先级降序
// 返回匹配长度最长且优先级最高的联系人列表
val maxMatchLength = scoredContacts.first().second.first
val maxPriority = scoredContacts.first().second.second
return scoredContacts
.filter { it.second.first == maxMatchLength && it.second.second == maxPriority }
.map { it.first }
.toMutableList()
}
// 计算从右向左的匹配长度
private fun calculateMatchLength(number1: String, number2: String): Int {
var matchLength = 0
val minLength = min(number1.length, number2.length)
// 从右向左逐位比较
for (i in 1..minLength) {
if (number1[number1.length - i] == number2[number2.length - i]) {
matchLength++
} else {
break // 遇到不匹配的字符,停止比较
}
}
return matchLength
}
//获取通话记录转发内容