Модераторы: diadiavova, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> DataGridView - одинаковые записи, как убрать/не добавлять 
:(
    Опции темы
BugZZ
Дата 21.10.2009, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 19.5.2008
Где: Germany

Репутация: нет
Всего: нет



Привет, Эксперты! 
Итак. Добрались руки до VS 2008 Sp1 и до парочки XML документов, которые надо прочитать
Начну с задумки:

Сделать тулзу которая читает n-е кол-во XML документов и из них всех вытаскивает только один определённый элемент и записывает его значение в DataGridView

Что реализовано:
 - выбор неопребеделённого кол-ва файлов черех OpenFileDialog
 - чтение всех выбраных фалоф на предмет нужного эелемента 
 - сохраниние содержания элемента в "таблицу" (ДатаГридВью)

проблема: 
 - после прочтение более чем однго файла, в DGV (DataGridView) появляюся одинаковые записи - что абсолютно нормально

пояснение:
 - каждый xml файл - это результат онлайн воутинга к фотографиям. К каждому JPG был создан XML в котором написано с какого ИП какую оценку поставили. Чтоб небыло жульничество, в XML сохраняются ТОЛЬКО разные ИП - повторов нет. 
НО, с одного ИП было проголосовано за несколько фотографий - отсюда один ИП может быть записан сразу в нескольких xml-файлах. Отсюда и двойные, тройные ... n-e записи одного ИП в DGV после прочтения БОЛЕЕ ОДНОГО xml-файлов

Цель:
 - Заставить XMLTextReader сохранять данные элемента только в том случае если запись НЕ присутвует в DGV

моя логика, которая к сожалению не работает, точнее реализовать которую так и не получилось....:
1. Если DGv - пуст -> читаю первый xml-файл в DGv
2. Если DGV НЕ пуст -> проверяю, при добавлении новой записи, есть ли в DGV уже такая. НЕТ - добавляю. ДА - иду дальше...

пример XML-файла:
Код

<ratings>
    <rating>
        <userid>0</userid>
        <username>213.182.125.18</username>
        <date>14:21:08 12-Sep-2009</date>
        <mark>5</mark>
    </rating>
    <rating>
        <userid>0</userid>
        <username>79.226.188.115</username>
        <date>14:58:47 12-Sep-2009</date>
        <mark>5</mark>
    </rating>
    <rating>
        <userid>0</userid>
        <username>84.135.202.249</username>
        <date>15:13:22 12-Sep-2009</date>
        <mark>1</mark>
    </rating>
    <rating>
        <userid>0</userid>
        <username>79.197.108.160</username>
        <date>16:14:09 12-Sep-2009</date>
        <mark>5</mark>
    </rating>
    <rating>
        <userid>0</userid>
        <username>212.100.60.181</username>
        <date>18:41:28 12-Sep-2009</date>
        <mark>1</mark>
    </rating>
    <rating>
        <userid>0</userid>
        <username>84.134.178.188</username>
        <date>21:21:28 12-Sep-2009</date>
        <mark>1</mark>
    </rating>
    <rating>
    .............
    </rating>
</ratings>


в DGV должны сохранятся ТОЛЬКО ИП. Тобиш значение элемента <username>


код, который добавляет все найденые username во всех выделенных файлах
Код

Imports System.Xml

Public Class Form1

    Private Sub btn_add_ips_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_add_ips.Click
        If myOpenFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
            lst_loaded_files.Visible = True
            lbl_dateien.Visible = True
            Dim List_with_path As Array = (myOpenFileDialog.FileNames)
            lst_loaded_files.Items.Clear()
            lst_loaded_files.Items.AddRange(myOpenFileDialog.SafeFileNames)
            dgv_ips.Rows.Clear()
            For i As Integer = 0 To List_with_path.Length - 1


                Dim myXmlReader As New XmlTextReader(List_with_path(i).ToString)
                While myXmlReader.Read()
                    If myXmlReader.NodeType = XmlNodeType.Element And myXmlReader.Name = "username" Then
                        dgv_ips.Rows.Add(myXmlReader.ReadElementString)
                    End If
                End While
            Next
        End If
        dgv_ips.Sort(dgv_ips.Columns(0), System.ComponentModel.ListSortDirection.Ascending)
        lst_loaded_files.ForeColor = Color.Green()
    End Sub


Буду рад советам, подсказам ну или какой-либо другой инфе. 

скрин, после прочтения 8ми фалов Как видно из картинки, некоторые ИП записаны все 8 раз .....
PM MAIL ICQ   Вверх
diadiavova
Дата 22.10.2009, 01:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Цитата(BugZZ @  21.10.2009,  23:42 Найти цитируемый пост)
онлайн воутинга к фотографиям.

 smile 

Забей данные в промежуточную коллекцию, потом отфильтруй функцией Distinct с самописным компэарером.

Код

Public Class Form1
    Sub FillGrid()
        'создаём список
        Dim rowList As New List(Of DataGridViewRow)
        'здесь список заполняется 
        'путём загрузки XML

        'создаём компэарер
        Dim comp As New RowComparer
        'Ну b добавляем в грид
        Me.DataGridView1.Rows.AddRange(rowList.Distinct(comp))

    End Sub
End Class

Class RowComparer
    Implements IEqualityComparer(Of DataGridViewRow)

    Public Function Equals1(ByVal x As System.Windows.Forms.DataGridViewRow, ByVal y As System.Windows.Forms.DataGridViewRow) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of System.Windows.Forms.DataGridViewRow).Equals
        Return x.Cells("ip").Value = y.Cells("ip").Value
    End Function

    Public Function GetHashCode1(ByVal obj As System.Windows.Forms.DataGridViewRow) As Integer Implements System.Collections.Generic.IEqualityComparer(Of System.Windows.Forms.DataGridViewRow).GetHashCode
        Return obj.Cells("ip").Value
    End Function
End Class


В данном примере я показал следующее:
Сначала по результату обработки файлов создаётся коллекция готовых строк для вставки в грид. Предполагается, что в коллекции есть столбец, под названием "ip"с типом данных Integer. Тут всё просто. Если есть IP к примеру такой 123.326.4.34, то мы вставляем в эту колонку число 123326004034.
Таким образом в этой колонке у нас будет одинаковое число при одинаковых IP.  Далее при вызове метода Distinct будет возвращена коллекция без повторов. 

Здесь весь секретв классе RowComparer. Функция Equals1 у него должна возвращать значение, указывающее равны ли объекты, а GetHashCode1 возвращать одинаковое значение для одинаковых объектов. Если правильно реализуешь логику сравнения, то код заполнения таблицы будет работать как надо.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
BugZZ
Дата 22.10.2009, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 19.5.2008
Где: Germany

Репутация: нет
Всего: нет



Цитата(diadiavova @  21.10.2009,  22:40 Найти цитируемый пост)
онлайн воутинга к фотографиям.

smile 
 Тоже удивлялся. Это дело рук какой-то "мудрёной" CMS....

Цитата(diadiavova @  21.10.2009,  22:40 Найти цитируемый пост)
Предполагается, что в коллекции есть столбец, под названием "ip"с типом данных Integer.

Хммм а вот тут уже появятся другие проблемы
12.201.45.10 -> 122014510
122.0.145.10 -> 122014510

А вообще знакомый сказал, что у меня ошибка в стравениени.... Решением была бы функция которая возвращала тру\фалс если запись уже присутствует в датагрид
PM MAIL ICQ   Вверх
diadiavova
Дата 22.10.2009, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



BugZZ, не знаю, возможно я непонятно объяснил, попытаюсь сформулировать иначе.
Для того, чтобы иметь возможность удалить повторяющиеся элементы списка, нужно точно сформулировать по каким критериям следует определять совпадение элементов. В дотнете для этого существует интерфейс IEqualityComparer(Of T). Реализовав его в класе ты обязан определить два метода:

Equals - получает два объекта сравниваемого типа и выдаёт True в случае, если объекты следует считать равными(логику прописываешь сам).

GetHashCode - этот метод возвращает для каждого объекта некоторое число таким образом, чтобы равным объектам соответствовало одно и то же число.

Если такой класс будет реализован, то его экземпляр можно передать методу Distinct и он отфильтрует коллекцию по описанному в этом классе правилу сравнения.

На счёт свойства у грида, позволяющего исключать повторяющиеся записи не в курсе, может и есть.

Добавлено через 2 минуты и 13 секунд
Цитата(BugZZ @  22.10.2009,  14:23 Найти цитируемый пост)
Хммм а вот тут уже появятся другие проблемы
12.201.45.10 -> 122014510
122.0.145.10 -> 122014510

Ну я ведь не так описал. Каждый сегмент айпишника должен состоять из трёх разрядов, если меньше - заполняй нулями. В моём примере ведь так.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
BugZZ
Дата 22.10.2009, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 19.5.2008
Где: Germany

Репутация: нет
Всего: нет



Цитата(diadiavova @  22.10.2009,  10:36 Найти цитируемый пост)
Для того, чтобы иметь возможность удалить повторяющиеся элементы списка, нужно точно сформулировать по каким критериям следует определять совпадение элементов. В дотнете для этого существует интерфейс IEqualityComparer(Of T). Реализовав его в класе ты обязан определить два метода:

Equals - получает два объекта сравниваемого типа и выдаёт True в случае, если объекты следует считать равными(логику прописываешь сам).

GetHashCode - этот метод возвращает для каждого объекта некоторое число таким образом, чтобы равным объектам соответствовало одно и то же число.

Если такой класс будет реализован, то его экземпляр можно передать методу Distinct и он отфильтрует коллекцию по описанному в этом классе правилу сравнения.

На счёт свойства у грида, позволяющего исключать повторяющиеся записи не в курсе, может и есть.

Окей буду, пробовать. Просто после твоего поста, в очередной раз увидел что know-how у меня мало и многое - просто не знаю!

Цитата(diadiavova @  22.10.2009,  10:36 Найти цитируемый пост)
Ну я ведь не так описал. Каждый сегмент айпишника должен состоять из трёх разрядов, если меньше - заполняй нулями. В моём примере ведь так. 

Извиняй, я не сразу обратил внимание.  smile 
Как добъюсь результатов - отпишусь....
PM MAIL ICQ   Вверх
diadiavova
Дата 22.10.2009, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Цитата(BugZZ @  22.10.2009,  14:56 Найти цитируемый пост)
Просто после твоего поста, в очередной раз увидел что know-how у меня мало и многое - просто не знаю!
Для этого и существует форум smile 



--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
BugZZ
Дата 22.10.2009, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 19.5.2008
Где: Germany

Репутация: нет
Всего: нет



итак, пошел по легкому пути и сначала обкатал вариант с функцией которая говорит тру - если такой ИП уже есть и ФАЛС - если таких еще не обнаруженно.
итак вот функция:
Код

    Public Function IsElementValueAlreadySaved(ByVal DataGridView As Windows.Forms.DataGridView, ByVal compareString As String) As Boolean
        Dim result As Boolean = False
        For i As Integer = 0 To DataGridView.Rows.Count - 1
            ' IP - это имя столбца. Можено было бы и индекс использовать. Разницы нет.
            If DataGridView.Rows.Item(i).Cells("ip").Value.Equals(compareString) Then
                result = True
                Exit For
            End If
        Next
        Return result
    End Function


функцию я потестил. Все работает и делает то, что от нее требуется...

После проверки функции долго смеялся ибо выяснилось что мой myXmlReader почему то вообще без моего ведома творит что хочет.
итак. применяю фукцию.
Код

Dim myXmlReader As New XmlTextReader(List_with_path(i).ToString)
                myXmlReader.WhitespaceHandling = WhitespaceHandling.None
                While myXmlReader.Read()
                    If myXmlReader.NodeType = XmlNodeType.Element And myXmlReader.Name.Equals("username") Then
                        If Not IsElementValueAlreadySaved(dgv_ips, myXmlReader.ReadElementString.Trim) Then
                            dgv_ips.Rows.Add(myXmlReader.ReadElementString.Trim)
                        End If
                    End If
                End While

запускаю тулзу и вижу что вместо ИП-адресов записаны даты-воутенга, хотя о них в коде НЕТ НИ СЛОВА! 
Вобщем, после проверок, пришел к вывроду что по каким-т непонятным причинам, XMLReader действует по след. принципу:
1 - читает документ
2 - Элемент и тебя зовут "username"? ДА!
 2.1 Ты уже есть в списке (ДГВ) ? ДА
  2.2 Беру след Элемент в файле (<date>)
 -----а все даты уникальны. Повторов нет! 

может конечно и не совсем так, но причина по которой ни с того ни с сяго берётся другой НИГДЕ НЕДЕКЛАРИРОВАННЫЕ элемент- мне не ясна......

Это сообщение отредактировал(а) BugZZ - 22.10.2009, 15:48
PM MAIL ICQ   Вверх
Pilger
Дата 22.10.2009, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 257
Регистрация: 10.5.2008
Где: Германия

Репутация: нет
Всего: нет



Попробуй myXmlReader.ReadElementString.Trim сначала в переменную поместить, а уже оттуда в функцию и в столбец. Проблема в том, что ReadElementString после прочтения сам перескакивает на сл. элемент, а т.к. ты его вызываешь 2 раза, то он соответственно сдвигается два раза. В функцию засовывается то что надо, а в столбец сл. элемент.
Да и в экономическом плане удобнее. Зачем вызывать myXmlReader.ReadElementString.Trim дважды, когда можно записать в переменную.

Это сообщение отредактировал(а) Pilger - 22.10.2009, 16:50


--------------------
Ein Leben nach der Schleife existiert, nur wenn die Schleife terminiert.
PM MAIL ICQ   Вверх
BugZZ
Дата 22.10.2009, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 19.5.2008
Где: Germany

Репутация: нет
Всего: нет



Цитата(Pilger @ 22.10.2009,  13:47)
Попробуй myXmlReader.ReadElementString.Trim сначала в переменную поместить, а уже оттуда в функцию и в столбец. Проблема в том, что ReadElementString после прочтения сам перескакивает на сл. элемент, а т.к. ты его вызываешь 2 раза, то он соответственно сдвигается два раза. В функцию засовывается то что надо, а в столбец сл. элемент.
Да и в экономическом плане удобнее. Зачем вызывать myXmlReader.ReadElementString.Trim дважды, когда можно записать в переменную.

Макс, ты как обычно не подкачал. Все заработало.
Решение :
Код

Dim myXmlReader As New XmlTextReader(List_with_path(i).ToString)
                myXmlReader.WhitespaceHandling = WhitespaceHandling.None
                While myXmlReader.Read()
                    If myXmlReader.NodeType = XmlNodeType.Element And myXmlReader.Name.Equals("username") Then
                        Dim element As String = myXmlReader.ReadElementString.Trim
                        If Not IsElementValueAlreadySaved(dgv_ips, element) Then
                            dgv_ips.Rows.Add(element)
                        End If
                    End If
                End While


Макс, тебе плюсик!
PM MAIL ICQ   Вверх
diadiavova
Дата 22.10.2009, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Цитата(BugZZ @  22.10.2009,  16:47 Найти цитируемый пост)
итак, пошел по легкому пути
Ну если это лёгкий путь тада извиняйте. В таком случае гораздо проще было перед добавлением новой строки в грид просто в цикле обходить все существующие и проверять, есть ли уже строка с таким айпи.



--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Pilger
Дата 22.10.2009, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 257
Регистрация: 10.5.2008
Где: Германия

Репутация: нет
Всего: нет



В общем то он так и сделал^^

 smile  100 сообщений. Щас буду плюсиками раскидываться.


--------------------
Ein Leben nach der Schleife existiert, nur wenn die Schleife terminiert.
PM MAIL ICQ   Вверх
diadiavova
Дата 22.10.2009, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Кстати, если бы он использовал лист, то вообще можно было без цикла обойтись...метод Find, передаёшь ему функцию(точнее лямбду) сравнивающую айпишники и сопсно всё. Но это не комильфо. Небольшое изменение условий потребует переписывания всего кода, а в моём случае переписать придётся только функции сравнения в компораторе.

Кстати тоже юбилей сегодня 2000+ в песочнице smile 


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
diadiavova
Дата 24.10.2009, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Кстати: на счёт интерфейса...вот тут описал более-менее универсальную реализацию.
http://forum.vingrad.ru/forum/topic-277734...ethashcode.html


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума VB .NET
diadiavova
  • Прежде чем задать вопрос, воспользуйтесь поиском: возможно Ваш вопрос уже обсуждался и на него был получен ответ.
  • Если такой же вопрос не найден, не стоит задавать свой вопрос в любую тему, создайте новую.
  • Заголовок темы должен отображать ее суть.
  • Содержание поста должно описывать проблему понятно, но в то же время, по возможности, лаконично. Сначала следует описать суть вопроса, потом можно привести пример кода, не вынуждайте других участников угадывать в чем Ваша проблема - телепатов здесь нет.
  • Будьте взаимно вежливы и дружелюбны.
  • При оформлении сообщений используйте форматирование, примеры кода заключайте в теги [CODE=vbnet][/CODE].
  • Также ознакомьтесь с общими правилами, действующими на всем форуме.
  • Если вопрос решен, не забывайте помечать тему решенной(вверху темы есть ссылка). Кроме того, если Вы хотите отблагодарить участников, оказавших помощь в решении, можно повысить им репутацию, в случае, если у Вас менее 100 сообщений в форуме и функция изменения репутации Вам недоступна, можете написать сюда.
  • Общие вопросы по программированию на платформе .NET обсуждаются здесь.
  • Литература по VB .NET обсуждается здесь.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, diadiavova.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | VB .NET | Следующая тема »


 




[ Время генерации скрипта: 0.0600 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.