Вот простой пример работы со списком списков (в соответствии с вашими примерами) с минимальным размером листовых массивов, передаваемых в качестве параметра (в вашем случае - 2).
Отображение извлекает ключ и накапливает массивы, в то время как нормализация рекурсивно уменьшает массивы, пока не будет достигнут удовлетворительный результат.
var arr = [
['a1','b1','c1','d1'],
['a1','e1','i1','j1'],
['a1','f1','k1','l1'],
['a1','g1','m1','n1'],
['a1','h1','o1','p1'],
['a2','b2','c2','d2'],
['a2','e2','i2','j2'],
['a2','f2','k2','l2'],
['a2','g2','m2','n2'],
['a2','h2','o2','p2']
];
console.log(transform(arr, 2));
function transform(input, minSize) {
return normalize(map(input, {}), minSize);
function map(input, result) {
for (var ii = 0; ii < input.length; ii++) {
var row = input[ii];
if (row.length == 0) {
continue;
}
var first = row[0];
var list = result[first] || (result[first] = []);
list.push(cdr(row));
}
return result;
}
function normalize(result, minSize) {
for (var key in result) {
var list = result[key];
if (list.length == 0) {
continue;
}
var first = list[0];
if (list.length == 1 && first.length <= minSize) {
result[key] = first;
continue;
}
result[key] = transform(list, minSize);
}
return result;
}
function cdr(list) {
var result = [];
for (var ii = 1; ii < list.length; ii++) {
result.push(list[ii]);
}
return result;
}
}
Когда у Вас есть результат, можно добраться, индексируемый текст передают его наряду с запросом через метод, подобный этому:
public string GeneratePreviewText(Query q, string text)
{
QueryScorer scorer = new QueryScorer(q);
Formatter formatter = new SimpleHTMLFormatter(highlightStartTag, highlightEndTag);
Highlighter highlighter = new Highlighter(formatter, scorer);
highlighter.SetTextFragmenter(new SimpleFragmenter(fragmentLength));
TokenStream stream = new StandardAnalyzer().TokenStream(new StringReader(text));
return highlighter.GetBestFragments(stream, text, fragmentCount, fragmentSeparator);
}