.NET C # - количество отдельных массивов в массиве - PullRequest
1 голос
/ 05 января 2012

Я новичок здесь и немного неопытен с C #. Я искал в документации MSDN и Google, но не могу найти ответ на этот вопрос (я пытаюсь сформулировать это как можно более широко):

Я хочу сохранить упорядоченную последовательность целых чисел фиксированной длины в списке или массиве, а затем создать массив из этих целочисленных массивов. Кто-нибудь знает, как я могу подсчитать количество различных целочисленных массивов и какие конкретные типы данных я должен использовать (список, простой массив и т. Д.)? У меня нет точного кода, с которым я работал, но вот что-то похожее на то, что я пробовал:

int[] set1 = {2, 56, 8};
int[] set2 = {8, 25, 90};
int[] set3 = {2, 56, 8};

var superset = new List<int[]>;
superset.Add(set1);
superset.Add(set2);
superset.Add(set3);

Console.Out.WriteLine(superset.Distinct().Count());  //  would like this to output 2, but Distinct() doesn't seem to actually work and I would get 3

Ответы [ 5 ]

3 голосов
/ 05 января 2012

Вам просто нужно создать класс Comparer для целочисленного массива и передать его экземпляр методу Distinct.

Console.Out.WriteLine(superset.Distinct(new ArrayComparer()).Count());

Вот пример:

class ArrayComparer : IEqualityComparer<int[]>
{
    public bool Equals(int[] x, int[] y)
    {
        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        if (x.Length != y.Length)
            return false;

        //Check whether the arrays' values are equal.
        for(int i = 0; i < x.Length; i++){
            if(x[i] != y[i])
                return false;
        }

        // If got this far, arrays are equal
        return true;
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.

    public int GetHashCode(int[] intArray)
    {
        //Check whether the object is null
        if (Object.ReferenceEquals(intArray, null)) return 0;

        //Calculate the hash code for the array
        int hashCode = 0;
        bool isFirst = true;
        foreach(int i in intArray){
            if(isFirst) {
                hashCode = i;
                isFirst = false;
            }
            else
            {
                hashCode = hashCode ^ i;
            }
        }
        return hashCode;
    }
}

Этоработает для меня.Дает желаемый результат.

3 голосов
/ 05 января 2012

Метод Distinct имеет перегрузку, которая принимает экземпляр IEqualityComparer .Создайте реализацию IEqualityComparer для массива int (т.е. public class IntArrayComparer : IEqualityComparer<int[]>) и передайте экземпляр в вызов Distinct.

Метод SequenceEqual может быть полезным для реализации IEqualityComparer<int[]>.Equals, но это упражнение оставлено на ваше усмотрение.

0 голосов
/ 23 апреля 2015
 private int CountDistinct2DPoints(double[][] data)
    {
        Dictionary<Tuple<double, double>, int> pointsMap = new Dictionary<Tuple<double, double>, int>();
        for(int i = 0; i < data.Length; i++)
        {
            if (!pointsMap.ContainsKey(Tuple.Create(data[i][0], data[i][1])))
            {
                pointsMap.Add(Tuple.Create(data[i][0], data[i][1]), 1);
            }
            else
            {
                pointsMap[Tuple.Create(data[i][0], data[i][1])]++;
            }
        }
        return pointsMap.Keys.Count;
    }
0 голосов
/ 05 января 2012

Ни один из опубликованных ответов не объясняет, почему Distinct().Count() возвращает 3: причина в том, что Distinct() использует компаратор равенства по умолчанию для массивов, который сравнивает для равенства ссылок. Этот код вернет 2:

int[] set1 = {2, 56, 8}; 
int[] set2 = {8, 25, 90}; 
int[] set3 = set1;

var superset = new List<int[]>(); 
superset.Add(set1); 
superset.Add(set2); 
superset.Add(set3); 

Console.WriteLine(superset.Distinct().Count()); 

Как предполагают Боб и Ричард, вы можете преодолеть это, создав реализацию IEqualityComparer<int[]>, которая даст вам желаемое поведение.

0 голосов
/ 05 января 2012

Имейте в виду известную цитату:

«Умные структуры данных и тупой код работают намного лучше, чем наоборот».
- Эрик Рэймонд, Кафедральный собор и базар

Похоже, что цель в том, чтобы иметь возможность использовать простой и выразительный код (.Distinct()) для сравнения ваших данных. В этом случае я бы рекомендовал перейти с простых массивов на более богатые объекты. Примерно так:

class Numbers
{
  public int FirstNumber { get; set; }
  public int SecondNumber { get; set; }
  public int ThirdNumber { get; set; }
}

Тогда вы можете иметь массив этих объектов вместо массива массивов. Преимущество заключается в том, что вы можете наделить этот объект более богатой функциональностью. Такие как:

class Numbers : IEquatable<Numbers>
{
  public int FirstNumber { get; set; }
  public int SecondNumber { get; set; }
  public int ThirdNumber { get; set; }

  public bool Equals(Numbers other)
  {
    if (other == null)
      return false;
    return (
      this.FirstNumber == other.FirstNumber &&
      this.SecondNumber == other.SecondNumber &&
      this.ThirdNumber == other.ThirdNumber
    );
  }
}

Теперь ваш умный тип данных может более эффективно использоваться более тупым кодом. (Просто ссылаясь на цитату, не думайте, что вы пишете тупой код или что-то в этом роде.) Как правило, это предпочтительнее, поскольку вам не нужно переписывать логику сравнения в нескольких места, если это нужно использовать в нескольких местах. Логика сравнения происходит внутри типа данных, а не в процедурном коде.


Обратите внимание, что это непроверенный и код от руки . Если я что-то пропустил в реализации, поправьте меня:)

...