C # Как сравнить списокпункт к следующему? - PullRequest
0 голосов
/ 29 октября 2019

У меня есть List<string[]>, и я хотел бы сравнить массив first из списка с next , а затем распечатать части, которые равны в обоих строковых массивах.

Например:

public static void Main()
{
     List<string[]> list = new List<string[]>();
     string[] a = {"some", "random", "string"};
     string[] b = {"some", "other", "random", "string"};
     list.Add(a);
     list.Add(b);
     string[] difference = Compare(list);
}

public static string[] Compare (List<string[]> A)
{
     //do something here
}

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

Ответы [ 6 ]

2 голосов
/ 29 октября 2019

Давайте реализуем (в общем случае ) это с помощью Linq :

using System.Linq;

...

private static IEnumerable<T[]> Differences<T>(IEnumerable<IEnumerable<T>> source, 
                                               IEqualityComparer<T> comparer = null) {
  if (null == source)
    throw new ArgumentNullException(nameof(source));

  if (null == comparer)
    comparer = EqualityComparer<T>.Default;

  if (null == comparer)
    throw new ArgumentNullException(nameof(comparer), 
      $"No default comparer for {typeof(T).Name}");

  Dictionary<T, int> prior = null;

  foreach (var line in source) {
    Dictionary<T, int> current = line
      .GroupBy(item => item, comparer)
      .ToDictionary(chunk => chunk.Key, chunk => chunk.Count(), comparer);

    if (null != prior) 
      yield return current
        .Where(item => prior.ContainsKey(item.Key))
        .SelectMany(item => Enumerable
           .Repeat(item.Key, Math.Min(item.Value, prior[item.Key])))
        .ToArray();

    prior = current;
  }
}

Демо:

  List<string[]> list = new List<string[]>() {
    new []  { "some", "random", "string" },
    new []  { "some", "other", "random", "string" },
    new []  { "some", "some", "some" },
    new []  { "some", "some", "other" },
    new []  { "some", "other", "some" },
  };

  string demo = string.Join(Environment.NewLine, Differences(list)
    .Select(line => string.Join(", ", line)));

  Console.Write(demo);

Результат:

some, random, string  // 1st and 2nd strings
some                  // 2nd and  3d strings
some, some            //  3d and 4th strings 
some, some, other     // 4th and 5th strings

Если вы хотите, чтобы только 1-я строка , добавьте .FirstOrDefault():

string demo = Differences(list)
  .Select(line => string.Join(", ", line)) 
  .FirstOrDefault();

Console.Write(demo);

Результат:

some, random, string

Наконец, если вы хотите пересечь все элементы (общие элементы во всех строках):

    private static IEnumerable<T> IntersectAll<T>(IEnumerable<IEnumerable<T>> source, 
                                              IEqualityComparer<T> comparer = null) {
      if (null == source)
        throw new ArgumentNullException(nameof(source));

      if (null == comparer)
        comparer = EqualityComparer<T>.Default;

      if (null == comparer)
        throw new ArgumentNullException(nameof(comparer), 
          $"No default comparer for {typeof(T).Name}");

      Dictionary<T, int> prior = null;

      foreach (var line in source) {
        Dictionary<T, int> current = line
          .GroupBy(item => item, comparer)
          .ToDictionary(chunk => chunk.Key, chunk => chunk.Count(), comparer);

        if (null != prior)
          prior = current
            .Where(item => prior.ContainsKey(item.Key))
            .ToDictionary(item => item.Key, item => Math.Min(item.Value, prior[item.Key]));
        else
          prior = current;
      }

      return (prior ?? new Dictionary<T, int>())
        .SelectMany(item => Enumerable.Repeat(item.Key, item.Value));
    }
2 голосов
/ 29 октября 2019

1. Найти пересечения пар массивов в списке

private static IEnumerable<(string,string[])> Compare(List<(string Name,string[] Words)> lists)
{
    for(int i = 0; i < lists.Count - 1; i++) {
        var a = lists[i];
        var b = lists[i + 1];
        yield return ($"{a.Name}<->{b.Name}", a.Words.Intersect(b.Words).ToArray());
     }
}

Тест

Код

List<(string, string[])> list = new List<(string, string[])>();
string[] a = {"some", "random", "string"};
string[] b = {"some", "other", "random", "string"};
string[] c = {"some", "other2", "random", "string2"};
list.Add(("a", a));
list.Add(("b", b));
list.Add(("c", c));

foreach( var pair in Compare(list) )
        Console.WriteLine($"{pair.Item1}: {string.Join(", ", pair.Item2)}");

Выход

// .NETCoreApp,Version=v3.0
a<->b: some, random, string
b<->c: some, random

2. Найти слова во всех массивах

private static string[] InAll(List<string[]> lists)
{
    var inAll = new List<string>();
    foreach(var list in lists ) {
        foreach(var word in list) {
            if(lists.All(l => l.Contains(word))) {
                inAll.Add(word);
            }
        }
    }
    return inAll.Distinct().ToArray();
}

Тест

Код

public static void Main(string[] args)
{
    List<string[]> list = new List<string[]>();
    string[] a = {"some", "random", "string"};
    string[] b = {"some", "other", "random", "string"};
    string[] c = {"some", "other2", "random", "string2"};
    list.Add(a);
    list.Add(b);
    list.Add(c);

    foreach( var inAll in InAll(list) ) Console.WriteLine(inAll);
}

Вывод

// .NETCoreApp,Version=v3.0
some
random
0 голосов
/ 29 октября 2019

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

Результат:

Result Of Code

    public static IEnumerable<string> Compare(List<string[]> items)
    {
        var liste = new List<string>() ;
        AddingElements(items, liste);
        return liste.Distinct();
    }

    private static void AddingElements(List<string[]> items, List<string> liste)
    {
        items.Skip(1).ToList().ForEach((e) =>
        {
            liste.AddRange(e.Difference(items.First()));
        });
    }

    public static string[] Difference(this string[] sourceArray, string[] stringArray)
    {
        return sourceArray.Where(e => stringArray.Contains(e))
                          .ToArray();
    }
0 голосов
/ 29 октября 2019

Похоже, вам просто нужно пересечение всех массивов:

private static string[] GetCommonElements(List<string[]> list)
{
    if (!list.Any())
    {
        return Array.Empty<string>();
    }

    IEnumerable<string> result = list[0];

    foreach (string[] collection in list.Skip(1))
    {
        result = result.Intersect(collection);
    }

    return result.ToArray();
}
0 голосов
/ 29 октября 2019
public static string[] Compare(List<string[]> A)
{
    string result = string.Empty;
    foreach(string s in A[0])
    {
        if(A[1].Contains(s))
        {
            if(result==string.Empty)
            {
                result += s;
            }
            else
            {
                result += "," + s;
            }
        }
    }

    return result.Split(',');

}
0 голосов
/ 29 октября 2019

Для произвольного количества списков, которые нужно сравнить, вы могли бы написать что-то вроде этого:

public static string[] Compare (List<string[]> lists)
{
    var temp = lists.First().ToList();
    foreach(var l in lists)
    {
        temp = temp.Intersect(l).ToList();
    }
    return temp.ToArray();
}

Это приведет к

some
random
string

Конечно, вы добавите обработку ошибок в случае, еслипустого списка и так далее ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...