Mohamed Ahmed Ответов: 1

Подсчет дублированных элементов в массиве


Я пытаюсь извлечь блок атрибутов AutoCAD в excel


Вывод В Excel [^]

Мой вопрос заключается в том, как подсчитать дублированные элементы в массиве и добавить их в новый столбец

Что я уже пробовал:

List<object[]> rooms = new List<object[]>();
            using (var tr = db.TransactionManager.StartTransaction())
            {
                foreach (SelectedObject so in psr.Value)
                {
                    BlockReference bref = (BlockReference)tr.GetObject(so.ObjectId, OpenMode.ForRead);                    
                    Autodesk.AutoCAD.DatabaseServices.AttributeCollection attcoll = bref.AttributeCollection;
                    object[] info = new object[4];
                    foreach (ObjectId id in attcoll)
                    {
                        AttributeReference atref = (AttributeReference)tr.GetObject(id, OpenMode.ForRead);

                        if (atref.Tag=="ROOM")
                        {
                            info[0] = atref.TextString;
                        }
                        if (atref.Tag=="ROOMID")
                        {
                            info[1] = atref.TextString;
                        }
                        if (atref.Tag=="ROOMAREA")
                        {
                            info[2] = atref.TextString;
                        }

                        if (!rooms.Contains(info))
                        {
                            rooms.Add(info);
                        }
                    }
                }
                tr.Commit();
            }

BillWoodruff

Я не вижу в вашем коде ничего такого, что имело бы значение." Четко определите, что такое "дубликат".

1 Ответов

Рейтинг:
2

Maciej Los

Вместо List<object[]> я бы использовал Словарь[^].

Dictionary<string, int> myCounter = new Dictionary<string, int>();
using (var tr = db.TransactionManager.StartTransaction())
{
    foreach (SelectedObject so in psr.Value)
    {
        BlockReference bref = (BlockReference)tr.GetObject(so.ObjectId, OpenMode.ForRead);                    
        Autodesk.AutoCAD.DatabaseServices.AttributeCollection attcoll = bref.AttributeCollection;
        foreach (ObjectId id in attcoll)
        {
            AttributeReference atref = (AttributeReference)tr.GetObject(id, OpenMode.ForRead);
            if (atref.Tag.Contains("ROOM"))
                if (!myCounter.ContainsKey(atref.TextString))
                {
                    myCounter.Add(atref.TextString, 1);
                }
                else
                {
                    myCounter[atref.TextString] += 1; 
                }
        }
    }
}

//Dictionary object contains unique data with the number of occurences
Console.WriteLine("Key | Count");
foreach(var k in myCounter.Keys)
{
	Console.WriteLine("{0} | {1}", k, myCounter[k]);
}


Приведенный выше код должен возвращать что-то вроде этого:
Key | Count
ROOM | 5
ROOMID | 10
ROOMAREA | 15


#realJSOP

Если вы использовали HashSet- тебе не понадобится эта линия

if (!myCounter.ContainsKey(atref.TextString))
Попытка добавить элемент, который уже существует в HashSet коллекция будет проигнорирована (без создания исключения).

Maciej Los

Хорошая мысль!
- Спасибо, Джон. Я воспользуюсь им в следующий раз ;)

[РЕДАКТИРОВАТЬ]
Я пытался это осуществить HashSet<CustomClass(Name, Count)> с IEqualityComparer<CustomClass>, но это меня не удовлетворяет, потому что сравнение объектов по их названию не дает возможности увеличить счет.

#realJSOP

Почему вы не можете использовать Linq для получения количества уникальных предметов в коллекции?

Matt T Heffron

Но ... HashSet не отдам графа.
Это примерно эквивалентно Dictionary<T, bool> но если ключ присутствует то bool ценность-это всегда true.
(Или я что-то упускаю? .. )

Maciej Los

Мэтт, может быть, Джон хотел указать мне на Hashtable :)
[РЕДАКТИРОВАТЬ]
А может и нет ;(
Hastable выдает ошибку, когда ключ уже существует.

#realJSOP

HashSet действительно имеет свойство Count. В прошлом я использовал хэш-набор для подсчета уникальных цветов в изображении. Я даже опубликовал Совет/трюк по этому поводу.

https://www.codeproject.com/Tips/159307/Count-Number-of-Unique-Colors-in-an-Image

Я специально использовал хэш-набор, потому что он не создавал исключений при попытке добавить дубликат элемента.

Maciej Los

Как я уже упоминал, я создал CustomClass с двумя членами(свойствами): Name &Count. Я хотел добиться того же, что и выше. Если ключ существует, увеличьте количество.
Я последую твоему трюку.

Maciej Los

Похоже, что требование ОП совсем другое. Если я хорошо понимаю, ОП хочет посчитать дублированные элементы. Используя словарь, я могу перечислить все элементы и вернуть количество каждого элемента в словаре.

Matt T Heffron

Мацей,
Чтобы получить подсчеты каждого ключа, не нуждаясь в явном .ContainsKey() тест вы могли бы использовать несколько неясный класс System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue>
В вашем примере изменение Dictionary<string,int> быть ConcurrentDictionary<string,int> целый

if (!myCounter.ContainsKey(atref.TextString)){  myCounter.Add(atref.TextString, 1);}else{  myCounter[atref.TextString] += 1}
сворачивается до одного утверждения:
myCounter.AddOrUpdate(atref.TextString, 1, (k,v) => v + 1);
Конечно, это связано с затратами на защиту параллелизма, которые не являются необходимыми.

Matt T Heffron

Джон, пример Мацея имел подсчет количества дубликатов для каждого ключа. То .Count собственность компании HashSet это количество записей в коллекции, поэтому это количество ключей. (Нет даже количество ключей, которые имеют дубликаты.)