#c# #linq
#c# #linq
Вопрос:
Я получаю список объектов из внешней службы вида:
[
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'road',
'Relation': 'CAN_TRAVEL_ON'
},
{
'Sentence': 'Kunal Mukherjee can travel by own car on road.',
'Subject': 'Kunal',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'Kunal Mukherjee can travel by own car on road.',
'Subject': 'Kunal Mukherjee',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
}
]
Итак, моя цель — отфильтровать объекты из ответа, которые содержат друг друга,
{
'Sentence': 'Kunal Mukherjee can travel by own car on road.',
'Subject': 'Kunal',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'Kunal Mukherjee can travel by own car on road.',
'Subject': 'Kunal Mukherjee',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
}
В приведенных выше объектах в Subject
свойстве есть самая длинная общая строка Kunal Mukherjee
, поэтому фильтровать нужно только этот объект.
Другой пример:
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
}
Здесь в Object
свойстве own car
находится самая длинная общая строка из двух, поэтому ее следует взять.
Итак, окончательный отфильтрованный список должен выглядеть примерно так:
[
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'road',
'Relation': 'CAN_TRAVEL_ON'
},
{
'Sentence': 'Kunal Mukherjee can travel by own car on road.',
'Subject': 'Kunal Mukherjee',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
}
]
Итак, я пытаюсь таким образом сравнить каждый ith
и i 1th
элемент для правила, которое:
- Если
ith
элементSubject
содержитi 1th
elementSubject
, возьмите его и наоборот. - Если
ith
элементObject
содержитi 1th
elementObject
, возьмите его и наоборот.
но он не отображается правильно.
static void Main(string[] args)
{
string data = @"[
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'C13 can travel by own car on road.',
'Subject': 'C13',
'Object': 'road',
'Relation': 'CAN_TRAVEL_ON'
},
{
'Sentence': 'Kunal Mukherjee can travel by own car on road.',
'Subject': 'Kunal',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
},
{
'Sentence': 'Kunal Mukherjee can travel by own car on road.',
'Subject': 'Kunal Mukherjee',
'Object': 'own car',
'Relation': 'CAN_TRAVEL_BY'
}
]";
List<JObject> js = JsonConvert.DeserializeObject<List<JObject>>(data);
var pairs = js.Take(js.Count - 1).Select((x, i) =>
{
string aSubj = js[i]["Subject"].ToString();
string bSubj = js[i 1]["Subject"].ToString();
string aObj = js[i]["Object"].ToString();
string bObj = js[i 1]["Object"].ToString();
if ((aSubj.Length > bSubj.Length amp;amp; aSubj.Contains(bSubj)) || (aObj.Length > bObj.Length amp;amp; aObj.Contains(bObj)))
{
return js[i];
}
if ((aSubj.Length > bSubj.Length amp;amp; aSubj.Contains(bSubj)) || (bObj.Length > aObj.Length amp;amp; bObj.Contains(aObj)))
{
return js[i 1];
}
return js[i];
}).ToList();
}
Это .NET fiddle для проверки этого.
Я буду признателен за любую помощь, которая поможет мне решить эту проблему.
Комментарии:
1. Что, если у одного элемента длина больше,
Subject
а у другого элемента длиннееObject
?2. Извините, но неясно, что именно вы ищете… Я понимаю, что вы получаете, но я не понимаю, чего вы хотите от этих данных…
3. Идея смежна,
Subject(s)
иObject(s)
необходимо сравнивать для самых длинных совпадений4. @KunalMukherjee
adjacent
в вашем вопросе не существует критериев5. @MartinVerjans Я создаю графическую базу данных, используя естественный язык и разделяя их с помощью стэнфордского сервиса CoreNLP, который выдает мне ответ в следующей форме
Ответ №1:
Вы можете создать метод (расширения), который уменьшает (фильтрует) ваши элементы:
public static IEnumerable<Item> Reduce(this IEnumerable<Item> items)
{
using (var iterator = items.GetEnumerator())
{
if (!iterator.MoveNext())
yield break;
var previous = iterator.Current;
while (iterator.MoveNext())
{
var next = iterator.Current;
var containsPrevious =
previous.Sentence == next.Sentence amp;amp;
next.Subject.Contains(previous.Subject) amp;amp;
next.Object.Contains(previous.Object);
if (!containsPrevious)
yield return previous;
previous = next;
}
yield return previous;
}
}
Правило простое — когда соседние элементы содержат одно и то же предложение, а последний элемент включает субъект и объект предыдущего элемента, тогда отбросьте первый элемент из результатов.
Использование простое:
var result = JsonConvert.DeserializeObject<List<Item>>(data).Reduce();
Обратите внимание, что вам нужен Item
класс (рассмотрите возможность использования лучших имен)
public class Item
{
public string Sentence { get; set; }
public string Subject { get; set; }
public string Object { get; set; }
public string Relation { get; set; }
}
Выходной сигнал:
[
{
"Sentence": "C13 can travel by own car on road.",
"Subject": "C13",
"Object": "own car",
"Relation": "CAN_TRAVEL_BY"
},
{
"Sentence": "C13 can travel by own car on road.",
"Subject": "C13",
"Object": "road",
"Relation": "CAN_TRAVEL_ON"
},
{
"Sentence": "Kunal Mukherjee can travel by own car on road.",
"Subject": "Kunal Mukherjee",
"Object": "own car",
"Relation": "CAN_TRAVEL_BY"
}
]
Комментарии:
1. 2 вопроса, 1)
while (iterator.MoveNext())
как итератор возвращается назад? 2) Почемуprevious = next;
2. Итератор переходит только вперед, поэтому я сохраняю предыдущий элемент.
previous = next
сохранить текущий элемент для следующей итерации