2015-03-29 4 views
0

Я хочу сравнить несколько форм имени человека. Иерархия рассмотрения является:Как сформулировать эту логику?

фамилии> имя> отчество,

с полным написанием> начальным,

с полными именами (первыми, середины, последняя)> частичных именами (первыми, последней)

пример:

< Джон Джон Кеннеди < < JFK JF Kennedy < Джон Ф. Кеннеди < Джон Фицджеральд Кеннеди

Так что, если мой человек объект может быть:

name_variant_1 = { 
    first: "John", 
    last: "Kennedy" 
} 

name_variant_2 = { 
    first: "J.", 
    mid: "F.", 
    last: "K." 
} 

, что это лучший способ, чтобы сравнить их для лучшего названия?

Я хочу сделать это с наиболее эффективной формулировкой, а не с разветвленной логикой. Я бы предпочел не использовать эвристику для оценки имени.

Спасибо!

+1

Любая причина, по которой вы явно предпочитаете краткость по читаемости? –

+0

@ IngoBürk: Потому что краткость очень важна здесь, чтобы показать иерархию, вместо того, чтобы потеряться при ветвлении. – Bergi

ответ

0

Я хочу сделать это с наиболее эффективной формулировкой, а не с разветвленной логикой.

Ну, в основном вы потребность ветвление логики, но есть несколько способов, чтобы сделать его менее болезненным. Есть два трюка:

  • if (a && !b) return 1; else if (!a && b) return -1; else return 0; может быть упрощена return a - b;
  • if (a != 0) return a; else return b; может быть упрощена return a || b;

Таким образом, можно сформулировать логику сравнения, как

function hasFullName(x) { 
    return ('first' in x) && ('mid' in x) && ('last' in x); 
} 
function isInitial(x) { 
    return x.charAt(x.length - 1) == "."; 
} 
function comparePart(a, b) { 
    return (!!a - !!b) // part exists at all? 
     || (isInitial(b) - isInitial(a)); 
} 

function compare(a, b) { 
    return (hasFullName(a) - hasFullName(b)) // full names always win 
     || comparePart(a.last, b.last) 
     || comparePart(a.first, b.first) 
     || comparePart(a.mid, b.mid); 
} 

Тест:

> [{"first":"J.","mid":"F.","last":"K."},{"first":"J.","mid":"F.","last":"Kennedy"},{"first":"John","mid":"F.","last":"Kennedy"},{"first":"John","mid":"Fitzgerald","last":"Kennedy"},{"first":"John"},{"first":"John","last":"Kennedy"}] 
> .sort(compare) 
[{"first":"John"},{"first":"John","last":"Kennedy"},{"first":"J.","mid":"F.","last":"K."},{"first":"J.","mid":"F.","last":"Kennedy"},{"first":"John","mid":"F.","last":"Kennedy"},{"first":"John","mid":"Fitzgerald","last":"Kennedy"}] 
+0

Это фантастический ответ и то, что я ищу! Можете ли вы объяснить обоснование: if (a &&! B) return 1; else if (! a && b) return -1; else return 0; может быть упрощено для возврата a-b; Что делает логическое - boolean? – kaid

+1

@Ninjack: он отличает их к номерам ('true -> 1',' false -> 0'), а затем вычитает их. – Bergi

+0

Каково ваше эмпирическое правило, зная, когда использовать этот трюк? Я определенно хотел бы использовать его в будущем. Это похоже на странный XOR? – kaid

Смежные вопросы