Files
tangfamily/test-fixed-sort.js
2026-06-24 22:13:01 +08:00

137 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 完整测试新算法
const members = [{"id":"4661dd7b","name":"唐治明","birthYear":1960,"gender":"男","generation":"父亲","fatherId":"f24a95c7"},{"id":"d4498bfb","name":"舒邦莲","birthYear":1960,"gender":"女","generation":"父亲"},{"id":"f24a95c7","name":"唐有奎","birthYear":1900,"gender":"男","generation":"祖父"},{"id":"1be537aa","name":"唐治安","birthYear":1960,"gender":"男","generation":"父亲","fatherId":"f24a95c7"},{"id":"e6d9c5b3","name":"万华群","birthYear":1960,"gender":"女","generation":"父亲"},{"id":"4b78f55d","name":"唐治芳","birthYear":1960,"gender":"女","generation":"父亲","fatherId":"f24a95c7"},{"id":"a7bcc3b5","name":"邓能春","birthYear":1960,"gender":"男","generation":"父亲"}];
const map = {};
members.forEach(m => map[m.id] = m);
const families = {
'4661dd7b|d4498bfb': { fatherId: '4661dd7b', motherId: 'd4498bfb' },
'1be537aa|e6d9c5b3': { fatherId: '1be537aa', motherId: 'e6d9c5b3' },
'a7bcc3b5|4b78f55d': { fatherId: 'a7bcc3b5', motherId: '4b78f55d' }
};
const familyKeyOfChild = {
'4661dd7b': 'f24a95c7|',
'1be537aa': 'f24a95c7|',
'4b78f55d': 'f24a95c7|'
};
const prevOrderIndex = { 'f24a95c7': 0 };
const row = members;
const memberSet = new Set(row.map(m => m.id));
// 1. 识别配偶关系
const spouseOf = {};
Object.keys(families).forEach(key => {
const fam = families[key];
if (!fam || !fam.fatherId || !fam.motherId) return;
if (memberSet.has(fam.fatherId) && memberSet.has(fam.motherId)) {
spouseOf[fam.fatherId] = fam.motherId;
spouseOf[fam.motherId] = fam.fatherId;
}
});
// 2. 按血缘分组
const siblingGroups = {};
row.forEach(m => {
const key = familyKeyOfChild[m.id] || `solo:${m.id}`;
if (!siblingGroups[key]) siblingGroups[key] = [];
siblingGroups[key].push(m);
});
console.log('兄弟姐妹分组:');
Object.keys(siblingGroups).forEach(key => {
console.log(` ${key}: ${siblingGroups[key].map(m => m.name).join(', ')}`);
});
// 3. 构建家庭单元
const familyUnits = [];
const globalProcessed = new Set();
function compareByBirthName(a, b) {
if (a.birthYear !== b.birthYear) return b.birthYear - a.birthYear;
return a.name.localeCompare(b.name, 'zh-Hans-CN');
}
Object.keys(siblingGroups).forEach(groupKey => {
const siblings = siblingGroups[groupKey].slice().sort(compareByBirthName);
const unitMembers = [];
siblings.forEach(person => {
if (globalProcessed.has(person.id)) return;
globalProcessed.add(person.id);
const spouseId = spouseOf[person.id];
if (spouseId && memberSet.has(spouseId)) {
globalProcessed.add(spouseId);
const spouse = map[spouseId];
if (person.gender === '男') {
unitMembers.push(person, spouse);
} else {
unitMembers.push(spouse, person);
}
} else {
unitMembers.push(person);
}
});
if (unitMembers.length > 0) {
familyUnits.push({ groupKey, members: unitMembers });
}
});
console.log('\n家庭单元:');
familyUnits.forEach((unit, i) => {
const names = unit.members.map(m => m.name).join(' + ');
console.log(` Unit ${i} (${unit.groupKey}): ${names}`);
});
// 4. 计算权重并排序
function getUnitWeight(unit) {
const key = unit.groupKey;
if (key.startsWith('solo:')) {
return { parentIdx: 9999, birthYear: unit.members[0].birthYear };
}
const parts = key.split('|');
const fId = parts[0] || null;
const mId = parts[1] || null;
const indices = [];
if (fId && prevOrderIndex[fId] !== undefined) indices.push(prevOrderIndex[fId]);
if (mId && prevOrderIndex[mId] !== undefined) indices.push(prevOrderIndex[mId]);
const parentIdx = indices.length > 0 ? Math.min(...indices) : 9999;
const birthYear = Math.max(...unit.members.map(m => m.birthYear));
return { parentIdx, birthYear };
}
familyUnits.sort((a, b) => {
const wa = getUnitWeight(a);
const wb = getUnitWeight(b);
if (wa.parentIdx !== wb.parentIdx) return wa.parentIdx - wb.parentIdx;
if (wa.birthYear !== wb.birthYear) return wb.birthYear - wa.birthYear;
return 0;
});
console.log('\n排序后的家庭单元:');
familyUnits.forEach((unit, i) => {
const names = unit.members.map(m => m.name).join(' + ');
const weight = getUnitWeight(unit);
console.log(` ${i}. ${names} (parentIdx=${weight.parentIdx}, birthYear=${weight.birthYear})`);
});
// 5. 展开为最终结果
const result = [];
familyUnits.forEach(unit => result.push(...unit.members));
console.log('\n最终排序结果:');
console.log(result.map(m => m.name).join(', '));
console.log('\n期望结果:');
console.log('唐治安, 万华群, 唐治芳, 邓能春, 唐治明, 舒邦莲, 唐有奎');
console.log('\n说明: 唐治安、唐治芳、唐治明都是唐有奎的孩子应该排在前面parentIdx=0');
console.log(' 舒邦莲、万华群、邓能春是外来配偶,紧贴在丈夫/妻子旁边');
console.log(' 唐有奎没有父母信息排到最后parentIdx=9999');