2016-04-12 5 views
1

У меня есть 4 списка.Каков наилучший способ сравнить несколько списков с различным количеством параметров

list1 = "hello" "hi" "bye" "lol" "rofl" "p1" "p2" "etc" 
list2 = "hello" "hi" "bye" "lol" "lmao" "c1" "apple" "mango" 
list3 = "hello" "hi" "bye" "lol" "rofl" "p1" "p2" "etc" "mango" "chair" "table" 
list4 = "hello" "hi" "bye" "lol" "rofl" "p1" "p2" "etc" "bus" "mango" "apple" "etc" 

Я хочу сделать сравнение между четырьмя списка и нужно сохранить параметры, совпадающие во всех списке, 3 списка, 2 списка, а не соответствующие параметры.

Что я могу использовать для сравнения нескольких списков, так как в списке могут быть n параметров, а n может варьироваться в каждом списке.

В настоящее время я кодирую tcl. Но любой алгоритм хорошо для меня

+0

Я не использую C++. Любой алгоритм может мне помочь – Nitesh

ответ

1

В PHP, решение было бы:

<?php 

// define lists (note the array_flip() calls) 
$list = array(); 
$list[] = array_flip(array("hello", "hi", "bye", "lol", "rofl", "p1", "p2", "etc")); 
$list[] = array_flip(array("hello", "hi", "bye", "lol", "lmao", "c1", "apple", "mango")); 
$list[] = array_flip(array("hello", "hi", "bye", "lol", "rofl", "p1", "p2", "etc", "mango", "chair", "table")); 
$list[] = array_flip(array("hello", "hi", "bye", "lol", "rofl", "p1", "p2", "etc", "bus", "mango", "apple", "etc")); 

// create a union of all lists where each member is present only once 
$keys = array(); 
for ($idx = 0; $idx<count($list); $idx++) { 
    $keys = $keys+$list[$idx]; 
} 

// iterate over the meta-list 
foreach (array_keys($keys) as $key) { 
    $found = array(); 
    for ($idx = 0; $idx<count($list); $idx++) { 
     if (isset($list[$idx][$key])) 
      $found[] = $idx; 
    } 
    printf('%s found in lists %s'.PHP_EOL, $key, join(', ', $found)); 
} 


?> 

Выходы:

hello found in lists 0, 1, 2, 3 
hi found in lists 0, 1, 2, 3 
bye found in lists 0, 1, 2, 3 
lol found in lists 0, 1, 2, 3 
rofl found in lists 0, 2, 3 
p1 found in lists 0, 2, 3 
p2 found in lists 0, 2, 3 
etc found in lists 0, 2, 3 
lmao found in lists 1 
c1 found in lists 1 
apple found in lists 1, 3 
mango found in lists 1, 2, 3 
chair found in lists 2 
table found in lists 2 
bus found in lists 3 

Demo. Обратите внимание, что это несколько оптимизаций для PHP, чтобы уменьшить сложность кода.

  • Сначала мы помещаем все списки ключевых слов в большой список. Мы используем array_flip(), чтобы ключевые слова были ключевыми, а не значениями.

  • Затем список всех ключевых слов создается путем простого добавления массивов (дублирование ключей переписывается, что является предполагаемым поведением в нашем случае).

  • Затем мы перебираем список всех ключевых слов. Каждое ключевое слово подсчитывается и отображается массив списков, в котором он находится.

+0

Я думаю, что есть путаница. Я не хочу, чтобы элементы отображались во всех списках. Я хочу каждый элемент и хочу найти, сколько списков они приходят с именами элементов. Как Hello - все, bye -all, только apple-list2 и list4, mango-list 2 и list3 – Nitesh

+0

@Nitesh Adapted. – syck

2

создать словарь, ключи которого являются словами и значениями являются целыми числами. Пройдите через каждый список, и если слово отсутствует, вставьте его со значением 1, если оно присутствует, увеличит его значение.

Чтобы узнать, сколько списков содержит слово, просто спросите словарь со словом в виде ключа.

+0

'foreach item $ list1 {dict incr itemcount $ item}' –

2

Вот некоторые TCL:

set list1 {hello hi bye lol rofl p1 p2 etc} 
set list2 {hello hi bye lol lmao c1 apple mango} 
set list3 {hello hi bye lol rofl p1 p2 etc mango chair table} 
set list4 {hello hi bye lol rofl p1 p2 etc bus mango apple etc} 

foreach var {list1 list2 list3 list4} { 
    foreach elem [set $var] { 
     lappend in($elem) $var 
    } 
} 
foreach {key lists} [array get in] { 
    lappend partition([llength $lists]) $key 
} 

Сейчас:

% parray in 
in(apple) = list2 list4 
in(bus) = list4 
in(bye) = list1 list2 list3 list4 
in(c1) = list2 
in(chair) = list3 
in(etc) = list1 list3 list4 list4 
in(hello) = list1 list2 list3 list4 
in(hi) = list1 list2 list3 list4 
in(lmao) = list2 
in(lol) = list1 list2 list3 list4 
in(mango) = list2 list3 list4 
in(p1) = list1 list3 list4 
in(p2) = list1 list3 list4 
in(rofl) = list1 list3 list4 
in(table) = list3 

% parray partition 
partition(1) = table lmao bus c1 chair 
partition(2) = apple 
partition(3) = p1 p2 mango rofl 
partition(4) = hi bye hello etc lol 
+0

Отлично. Можем ли мы получить список, напечатанный как 'apple', является частью списка – Nitesh

+0

Конечно. После строки 'incr count' добавьте' lappend in ($ elem) $ var', поэтому 'puts 'apple находится в $ in (apple)" ' –

+0

, поэтому мы больше не имеем массив count. –

1

Пусть этот массив списков:

set list(1) {hello hi bye lol rofl p1 p2 etc} 
set list(2) {hello hi bye lol lmao c1 apple mango} 
set list(3) {hello hi bye lol rofl p1 p2 etc mango chair table} 
set list(4) {hello hi bye lol rofl p1 p2 etc bus mango apple etc} 

Метод 1

set res {} 
set allWords [lsort -unique [concat $list(1) $list(2) $list(3) $list(4)]] 
foreach word $allWords { 
    set in {} 
    foreach i {1 2 3 4} { 
     if {$word in $list($i)} { 
      lappend in $i 
     } 
    } 
    lappend res $word $in 
} 

Алгоритм: создать список всех уникальных слов. Для каждого такого слова записывайте, если он встречается в каждом из списков в массиве. Верните список четных размеров, где пункт 0, 2, ... - это слово, а пункт 1, 3, ... - это номера списков, в которых встречается слово.

Метод 2

set res [concat {*}[lmap word $allWords { 
    list $word [lmap i {1 2 3 4} { 
     if {$word in $list($i)} { 
      set i 
     } else { 
      continue 
     } 
    }] 
}]] 

По существу то же самое, но использует 8.6 lmap команду Tcl.

Метод 3

unset res 
foreach i {1 2 3 4} { 
    foreach word $list($i) { 
     dict lappend res $word $i 
    } 
} 

алгоритм: для каждого списка и слова, lappend список номер к элементу в словаре res с ключом $word. Примечание: Это решение имеет недостаток, что если слово происходит более одного раза в одном списке, номер списка - lappend ed несколько раз.

Prettyprinting результат

lsort -unique из-за слабости в способе 3: это не является необходимым для других методов.

proc prettyPrint {word in} { 
    set in [lsort -unique $in] 
    switch [llength $in] { 
     0 {} 
     1 { 
      puts "$word is in list $in" 
     } 
     2 { 
      puts "$word is in list [join $in { and }]" 
     } 
     3 { 
      puts "$word is in lists [join $in {, }]" 
     } 
     4 { 
      puts "$word is in all lists" 
     } 
    } 
} 

foreach {w i} $res { 
    prettyPrint $w $i 
} 

(Список будет напечатан в другом порядке (слово для вставки заказа), если метод 3 используется.)

apple is in list 2 and 4 
bus is in list 4 
bye is in all lists 
c1 is in list 2 
chair is in list 3 
etc is in lists 1, 3, 4 
hello is in all lists 
hi is in all lists 
lmao is in list 2 
lol is in all lists 
mango is in lists 2, 3, 4 
p1 is in lists 1, 3, 4 
p2 is in lists 1, 3, 4 
rofl is in lists 1, 3, 4 
table is in list 3 

Документация: concat, continue, dict, foreach, if, lappend, list, llength, lmap, lmap замена, lsort, proc, set, switch, unset