СРОЧНО! Поиск duplicate в ArrayList и отображение в ListView

Язык C#: программирование на C#, портирование кода C# на VB и VB на C#.

Модератор: Ramzes

Thomas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 246
Зарегистрирован: 12.11.2005 (Сб) 0:17
Откуда: "Сказочное королевство"

СРОЧНО! Поиск duplicate в ArrayList и отображение в ListView

Сообщение Thomas » 29.04.2006 (Сб) 0:07

Приветствую всех.

Горю как Швед под Полтавой. :(
Знаю что должно произойти, но не знаю как это записать в коде. :oops:
А завтра утром решение должно быть у профессора на столе. А он, редиска не строевая, сегодня вечером на занятии не захотел подсказать. :cry:

В общем ситуация такая. Имеем список с данными на клиентов. Все это сохранено в ArrayList и отображается в ListView. В текс боксе вводим часть фамилии клиента(можно только первую букву) нажимаем ENTER и бинарный поиск находит клиента с фамилией, которая начинается на эту букву. Далее нужно искать остальных клиентов с фамилиями на эту букву.
Функция примерно такая
Код: Выделить всё
public void  Duplicate(ref int начало, ref int конец)
{
while(compare(ArrayList[начало], ArrayList[начало-1])==0 && начало>0)   
{
   начало--;
}
while(compare(ArrayList[конец], ArrayList[конец+1])==0 && конец<ArrayList.Count)
{
   конец++;
}      
}

То есть, что делает эта функция, она определяет границы(индексы) ArrayList содержащие клиентов с фамилиями начинающимися на одну букву. Передаем ей в качестве аргументов значение индекса найденного клиента с фамилией на эту букву.
Код: Выделить всё
Object чтоищем=txtZoekNaam.Text;
найденная_позиция=Klanten.BinarySearch(чтоищем, new Persoon.cmpVoorNaam()); // cmpVoorNaam()-это компарер написанный в классе Persoon


А теперь мне надо показать список этих клиентов в listView
Для этого пишу отдельную процедуру ПокажиКлиентов()
там по идее, пишем так
for(int i=начало; i=конец; i++)
{
тут нужно вставить код чтения данных из ArrayList и заполнения данными колонок ListView
}
Но мне ни как не сообразить как вызвать здесь Duplicate что бы получить индексы начала и конца???
:oops:

FaKk2
El rebelde gur&#250;
El rebelde gur&#250;
Аватара пользователя
 
Сообщения: 2031
Зарегистрирован: 09.03.2003 (Вс) 22:10
Откуда: Los Angeles

Сообщение FaKk2 » 29.04.2006 (Сб) 21:20

А что надо сделать? Выбрать из ArrayList все имена начинающиеся на указанную букву?
Для получения ответа надо продемонстрировать качества, позволяющие стать компетентным — внимательность, вдумчивость, наблюдательность, желание активно участвовать в выработке решения.

Thomas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 246
Зарегистрирован: 12.11.2005 (Сб) 0:17
Откуда: "Сказочное королевство"

Сообщение Thomas » 30.04.2006 (Вс) 14:37

приветствую всех.

FAKK2
В принципе из отсортированного по фамилиям списка (сохраненного в ArrayList) нужно выбрать всех клиентов, фамилии которых начинаются на заданный текст(это может быть и одна буква и фамилия целиком).
При использовании String.Compare(str, int,str,int,int) найти клиента не сложно. Далее от найденной позиции мы должны идти в право(вниз) или влево(вверх) по списку и проверить есть ли клиенты с фамилией начинающейся на указанный текст. Для этого написана отдельная функция Duplicate(ref int start, ref int end), которой мы в качестве параметров передаем гайденную позицию (два раза, т.е. мы начинаем проверку с одного места - start=end=найденной позиции).
Эта функция возвращает два значения. Это индекс начала и конца в ArrayList, между которыми находятся записи на клиентов с фамилиями начинающимися на указанный для поиска текст.
Далее данные этих клиентов нужно вывести в ListView, где можно выбрать нужного.

Да проект учебный и соответственно данные на клиентов и товар сгенерированы. В реальной жизни в программе должен быть предусмотрен ввод нормальных данных.
В общем я реализовал в конце концов это так:
- класс для клиентов
Код: Выделить всё

using System;
using StringFunctions;
using System.Collections;

namespace Verkoop
{
   public class Persoon
   {
   # region attributen
      int persNr;    ' номер клиента
      string vnm;   ' имя
      string nm;     ' фамилия
      string straatNr;    ' адрес
      string postcode;   ' почтовый индекс
      string gemeente;  'город
      DateTime gebDat;  ' дата рождения
      #endregion

   # region constructors
      public Persoon(int getal)
      {
         TimeSpan t;
         DateTime startdat= new DateTime(1980,1,1);
         persNr=getal;
         vnm=Globals.eigennaam(Globals.nrToString(getal+1));
         nm=Globals.nrToString(getal);
         straatNr=Globals.inverseer(nm)+" "+(getal%100);
         postcode=Convert.ToString((getal%100)*100+1000);
         gemeente=Globals.nrToString((getal%100)*100+1000);
         t=new TimeSpan(getal,0,0,0);
         if(getal%2==0)
            gebDat=startdat.Add(t);
         else
            gebDat=startdat.Subtract(t);
      }
      #endregion

   # region property

      public string PersoonNr
      {
         get{return persNr.ToString();}
      }
      public string VoorNaam
      {
         get{return vnm;}
      }
      public string FamilieNaam
      {
         get{return nm;}
      }
      public string Adres
      {
         get{return straatNr;}   
      }
      public string Postcode
      {
         get{return postcode;}
      }
      public string Woonplaats
      {
         get{return gemeente;}
      }
      public string Datum
      {
         get{return gebDat.ToShortDateString();}
      }

   #endregion

   #region vergelijking  ' методы для сравнения
      public class cmpNr:IComparer
      {
         int IComparer.Compare(object o1, object o2)
         {
            if(o2.GetType()==typeof(Persoon))
               return ((Persoon)o1).persNr - ((Persoon)o2).persNr;
            else
               return ((Persoon)o1).persNr - (int)o2;
         }
      }
      public class cmpVoorNaam:IComparer
      {
         int IComparer.Compare(object o1, object o2)
         {
            if(o2.GetType()==typeof(Persoon))
               return string.Compare(((Persoon)o1).vnm, ((Persoon)o2).vnm);
            else
               return string.Compare(((Persoon)o1).vnm,0,(string)o2,0,((string)o2).Length);
         }
      }
      public class cmpFamilieNaam:IComparer
      {
         int IComparer.Compare(object o1, object o2)
         {
            return string.Compare(((Persoon)o1).nm, ((Persoon)o2).nm);
         }
      }
      public class cmpZip:IComparer
      {
         int IComparer.Compare(object o1, object o2)
         {
            return string.Compare(((Persoon)o1).postcode, ((Persoon)o2).postcode);
         }
      }
      #endregion

   }
}


- класс описания товаров

Код: Выделить всё

using System;
using StringFunctions;
using System.Collections;

namespace Verkoop
{
   public class Artikel
   {
   #region attributen

      int artNr; 'номер товара
      string artNaam; 'наименование товара
      string barcode; 'Еаn13 код товара - это цыферки под баркодом
      double prijs; 'цена
      int voorraad; 'запас на скаладе (сток)
      int minstock; 'минимальный запас(сток)

   #endregion

   #region konstructors

      public Artikel(int volgnr)
      {
         artNr=volgnr+1000;
         artNaam=Globals.nrToString(volgnr);
         barcode=maakEan(artNr);
         prijs=volgnr+(volgnr/5.0);
         voorraad=volgnr/10;
         Random gen=new Random(volgnr);
         minstock=gen.Next(15);
      }

   #endregion

   #region property

      public string ArtNr
      {
         get{return artNr.ToString();}
      }
      public string ArtNaam
      {
         get{return artNaam;}
      }
      public string Barcode
      {
         get{return barcode;}
      }
      public double Prijs
      {
         get{return prijs;}
         set{prijs=value;}
      }
      public int Voorraad
      {
         get{return voorraad;}
         set{voorraad=value;}
      }
      public int Minstock
      {
         get{return minstock;}
         set{minstock=value;}
      }

   #endregion

   #region methods
'функция для создания Еаn13 кода по номеру страны 54, номеру фирмы производителя 8000 и номеру товара(6 следующих знаков). Последняя знак контрольная сумма. Всего 13 знаков.
      private string maakEan(long artNr)
      {
         int somE=0;
         int somO=0;
         int getal=0;
         string code, _artNr;
         _artNr=artNr.ToString();
         if(_artNr.Length<6)
         {
            int k=6-_artNr.Length;
            for(int n=0;n<k;n++)
            {
               _artNr="0"+_artNr;
            }
         }
         code="548000" + _artNr;
         for(int i=0;i<code.Length;i+=2)
         {
            somE+=Convert.ToInt32(code.Substring(i,1));
         }
         for(int j=1;j<code.Length;j+=2)
         {
            somO+=Convert.ToInt32(code.Substring(j,1));
         }
         getal=10-((somE+somO*3)%10);
         if(getal!=10)
            return code + getal.ToString();
         else
            return code + "0";

      }

   #endregion

   # region Vergelijking  ' сравнения

      public class cmpArtNr:IComparer
      {
         int IComparer.Compare(object o1, object o2)
         {
            if(o2.GetType()==typeof(Artikel))
               return ((Artikel)o1).artNr - ((Artikel)o2).artNr;
            else
               return ((Artikel)o1).artNr - (int)o2;
         }
      }
      public class cmpArtNaam:IComparer
      {
         int IComparer.Compare(object o1, object o2)
         {
            if(o2.GetType()==typeof(Artikel))
               return string.Compare(((Artikel)o1).artNaam, ((Artikel)o2).artNaam);
            else
               return string.Compare(((Artikel)o1).artNaam,0,(string)o2,0,((string)o2).Length);
         }
      }
      public class cmpBarcode:IComparer
      {
         int IComparer.Compare(object o1, object o2)
         {
            if(o2.GetType()==typeof(Artikel))
               return string.Compare(((Artikel)o1).barcode, ((Artikel)o2).barcode);
            else
               return string.Compare(((Artikel)o1).barcode,(string)o2);
         }
      }
      

   #endregion
   }
}



- и далее код на самой форме
Код: Выделить всё

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using StringFunctions;

namespace Verkoop
{
   public class Form1 : System.Windows.Forms.Form
   {
      #region Form elements
      [STAThread]
      static void Main()
      {
         Application.Run(new Form1());
      }
      
      private ArrayList Klanten = new ArrayList();   'обьявил список клиентов
      private ArrayList Artikelen = new ArrayList(); 'обьявил список товаров

      #region Form
      
      #region Klanten
' создаем список клиентов
      private void btnMaakKlant_Click(object sender, System.EventArgs e)
      {
         int n=10;
         DateTime dat= DateTime.Now;
         Random gen=new Random(dat.Millisecond);
         int loper;
         for(loper=0;loper<n;loper++)
         {
            Persoon p=new Persoon(gen.Next(997)); // создаем экземпляр класса
            if(Klanten.IndexOf(p)<0)
            {
               Klanten.Add(p); // записываем его в ArrayList
            }
            toonKlanten(); // показываем данные в листвью.
         }
      }
' показываем данные на клиентов в ListView
      private void toonKlanten()
      {
         int index=0;
         lstvKlant.Items.Clear();
         foreach(Persoon el1 in Klanten) // перебираем все элементы el1 типа  Persoon в ArrayList Klanten
         {
            lstvKlant.Items.Add((index+1).ToString());
            lstvKlant.Items[index].SubItems.Add(el1.PersoonNr.ToString());
            lstvKlant.Items[index].SubItems.Add(el1.VoorNaam);
            lstvKlant.Items[index].SubItems.Add(el1.FamilieNaam);
            lstvKlant.Items[index].SubItems.Add(el1.Adres +", " + el1.Postcode +", " + el1.Woonplaats);
            lstvKlant.Items[index++].SubItems.Add(el1.Datum);
         }
      }
' возможность сортировки по столбцам (по номеру. по фамилии и ...)
      private void lstvKlant_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)
      {
         switch(e.Column)
         {
            case 1:
               Klanten.Sort(new Persoon.cmpNr());
               break;
            case 2:
               Klanten.Sort(new Persoon.cmpVoorNaam());
               break;
            case 3:
               Klanten.Sort(new Persoon.cmpFamilieNaam());
               break;
            case 4:
               Klanten.Sort(new Persoon.cmpZip());
               break;
         }
         toonKlanten();
      }

      #endregion

      #region Artikelen
' создаем список товаров
      private void btnMaakArtikelen_Click(object sender, System.EventArgs e)
      {
         int n=10;
         DateTime dat= DateTime.Now;
         Random gen=new Random(dat.Millisecond);
         int loper;
         for(loper=0;loper<n;loper++)
         {
            Artikel a=new Artikel(gen.Next(997));
            if(Artikelen.IndexOf(a)<0)
            {
               Artikelen.Add(a);
            }
            toonArtikelen();
         }
      }
      'показываем товары в ListView
      private void toonArtikelen()
      {
         int index=0;
         lstvArtikel.Items.Clear();
         foreach(Artikel el1 in Artikelen) // el1 type Artikel(exemplayr classa) in ArrayList Artikelen
         {
            lstvArtikel.Items.Add((index+1).ToString());
            lstvArtikel.Items[index].SubItems.Add(el1.ArtNr);
            lstvArtikel.Items[index].SubItems.Add(el1.ArtNaam);
            lstvArtikel.Items[index].SubItems.Add(el1.Barcode);
            lstvArtikel.Items[index].SubItems.Add(el1.Prijs.ToString());
            lstvArtikel.Items[index].SubItems.Add(el1.Voorraad.ToString());
            lstvArtikel.Items[index++].SubItems.Add(el1.Minstock.ToString());
         }
      }
      #endregion

      #region Zoeken klanten
'ищем клиента по его номеру
      private void txtZoekNr_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
      {
         if(e.KeyChar==13)
         {
            lstvKl.Visible=false; 'не показываем lIstView предусмотренный для вывода дупликатов
            Klanten.Sort(new Persoon.cmpNr());
            int vindpos=-1;' впервоначальный момент ничего не нашли
            Object zoekwarde=int.Parse(txtZoekNr.Text);
            vindpos=Klanten.BinarySearch(zoekwarde, new Persoon.cmpNr());
            if(vindpos>=0) ' нашли найденная позиция положительна
            {
               Persoon data=(Persoon)(Klanten[vindpos]);
               lblKlantData.Text="KlantNr: "+data.PersoonNr+", Voornaam: "+data.VoorNaam+", Familienaam: "+data.FamilieNaam+", Adres: "+data.Adres+", "+data.Postcode+", "+data.Woonplaats+", Datum: "+data.Datum;
               txtZoekArtNr.Focus();
            }
            else ' не нашли найденнная позиция отрицательна
            {
               lblKlantData.Text="Klant met dit Nr bestaat niet. Probeer op nieuw.";
               txtZoekNr.Text="";
               txtZoekNr.Focus();
            }
         }
      }
' поиск клиента по имени или части имени
      private void txtZoekNaam_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
      {
         if(e.KeyChar==13)
         {
            lstvKl.Items.Clear();
            Klanten.Sort(new Persoon.cmpVoorNaam());
            int vindpos=-1; ' начало поиска
            Object zoekwarde=txtZoekNaam.Text;
            vindpos=Klanten.BinarySearch(zoekwarde, new Persoon.cmpVoorNaam());
            if(vindpos>=0) ' если нашли найденная позиция положительная
            {   'считываем данные на клмента из ArrayList в переменную data используя явный кастинг
               Persoon data=(Persoon)(Klanten[vindpos]);
               if(data.VoorNaam.Length==txtZoekNaam.Text.Length) 'если искали полное имя то пишем данные на клмента в label
                  lblKlantData.Text="KlantNr: "+data.PersoonNr+", Voornaam: "+data.VoorNaam+", Familienaam: "+data.FamilieNaam+", Adres: "+data.Adres+", "+data.Postcode+", "+data.Woonplaats+", Datum: "+data.Datum;
               else ' если искали и нашли по части имени то ищем дупликаты(всех клментов с именем начинающимся на искомый текст
               {
                  lstvKl.Visible=true; ' делаем видимым ListView для вывода данных
                  int begin=vindpos;
                  int end=vindpos;
                  Duplicate(ref begin, ref end);
                  int index=0;
                  for(int i=begin; i<end;  i++) 'выводим данные в ListView
                  {
                     data=(Persoon)(Klanten[i]);
                     lstvKl.Items.Add((index+1).ToString());
                     lstvKl.Items[index].SubItems.Add(data.PersoonNr.ToString());
                     lstvKl.Items[index].SubItems.Add(data.VoorNaam);
                     lstvKl.Items[index].SubItems.Add(data.FamilieNaam);
                     lstvKl.Items[index].SubItems.Add(data.Adres +", " + data.Postcode +", " + data.Woonplaats);
                     lstvKl.Items[index++].SubItems.Add(data.Datum);
                  }
               }
            }
            else 'если не нашли  if(vindpos>=0)
            {
               lblKlantData.Text="Klant met dit Naam bestaat niet. Probeer op nieuw.";
               txtZoekNaam.Text="";
               txtZoekNaam.Focus();
            }
         }
      }
'функция поиска дупликатов
            public void  Duplicate(ref int begin, ref int end)
            {
               Object zoekwarde=txtZoekNaam.Text;
               while(Klanten.BinarySearch(begin,1,zoekwarde, new Persoon.cmpVoorNaam())>0 && begin+1>0)   
               {
                  begin--;
               }
               while(end<Klanten.Count && Klanten.BinarySearch(end,1,zoekwarde, new Persoon.cmpVoorNaam())>0)
               {
                  end++;
               }
               
            } ' КАК Я ЭТО РЕАЛИЗОВАЛ МНЕ НЕ НРАВИТЬСЯ! Но  как заставить сравнивать элемент ArrayList с последующим я не смог записать в коде. Потому использовал функцию бинарного поиска с параметрами начала поиска и длинны проверяемого (в данном случае 1 позиция) для проверки стоит ли на данной позиции в ArrayList элемент с такой же частью имени или нет.
        'здесь мы выбираем из списка нужного клиента и выводим данные на него в label а ListView прячем  опять.
      private void lstvKl_SelectedIndexChanged(object sender, System.EventArgs e)
      {
         for(int i=0;i<lstvKl.Items.Count;i++)
         {
            if(lstvKl.Items[i].Selected)
            {
               lblKlantData.Text=lstvKl.Items[i].Text+", "+lstvKl.Items[i].SubItems[1].Text+", "+lstvKl.Items[i].SubItems[2].Text+", "+lstvKl.Items[i].SubItems[3].Text+", "+lstvKl.Items[i].SubItems[4].Text+", "+lstvKl.Items[i].SubItems[5].Text;
               txtZoekArtNr.Focus();
            }
         }
         lstvKl.Visible=false;
      }
      #endregion
   ' далее реализация продаж, тут мне все понятно и без проблем.
      #region Verkoop
      public Artikel dataArt;
      public int index; //artikel voor verkoop tonen
      public double BrPrijs, subtotaal;
      string tekst;
      private void txtZoekArtNr_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
      {
         if(e.KeyChar==13)
         {
            if(txtZoekArtNr.Text!="")
            {
               Artikelen.Sort(new Artikel.cmpArtNr());
               //Artikelen.Sort(new Artikel.cmpBarcode()); // zoeken op 'ean13' code
               int vindposArt=-1;
               Object zoekArt=int.Parse(txtZoekArtNr.Text);
               //Object zoekArt=txtZoekArtNr.Text; // zoeken op 'ean13' code
               vindposArt=Artikelen.BinarySearch(zoekArt,new Artikel.cmpArtNr());
               //vindposArt=Artikelen.BinarySearch(zoekArt,new Artikel.cmpBarcode()); // zoeken op 'ean13' code
               if(vindposArt>=0)
               {
                  dataArt=(Artikel)Artikelen[vindposArt];
                  lblArtNaam.Text=dataArt.ArtNaam;
                  lblArtPrijs.Text=dataArt.Prijs.ToString();
                  txtAantalArt.Focus();
               }
            }
            else
            {
               verkocht(); // volgende klant
            }
         }
      
      }

      private void txtAntaalArt_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
      {
         if(e.KeyChar==13)
         {
            int aantalArt=int.Parse(txtAantalArt.Text);
            if(aantalArt<Convert.ToInt32(dataArt.Voorraad))
            {
               subtotaal=aantalArt * Convert.ToDouble(dataArt.Prijs);
               lblSubTotaal.Text=subtotaal.ToString();
               btnOK.Focus();
               dataArt.Voorraad-=aantalArt;
               toonArtikelen();
            }
            else
            {
               MessageBox.Show("Oeps!We heben zo veel niet!","Voorraad is leeg!");
               txtAantalArt.Text="";
               txtAantalArt.Focus();
            }
         }
      }

      private void btnOK_Click(object sender, System.EventArgs e)
      {
         //artikel voor verkoop tonen
         lstvVerkoop.Items.Add((index+1).ToString());
         lstvVerkoop.Items[index].SubItems.Add(txtZoekArtNr.Text);
         lstvVerkoop.Items[index].SubItems.Add(lblArtNaam.Text);
         lstvVerkoop.Items[index].SubItems.Add(txtAantalArt.Text);
         lstvVerkoop.Items[index].SubItems.Add(lblArtPrijs.Text);
         lstvVerkoop.Items[index++].SubItems.Add(lblSubTotaal.Text);
         //totaal verkoop berekenen en tonen
         double BTW,Totaal;
         BrPrijs+=subtotaal;
         BTW=BrPrijs*0.21;
         Totaal=BrPrijs+BTW;
         lstvTotaalVerkoop.Items.Clear();
         int ind=0;
         lstvTotaalVerkoop.Items.Add(BrPrijs.ToString());
         lstvTotaalVerkoop.Items[ind].SubItems.Add(BTW.ToString());
         lstvTotaalVerkoop.Items[ind].SubItems.Add(Totaal.ToString());
         // eind verkoop voor dit klant voorbereiden
         tekst="Totaal te betalen: " + Totaal.ToString()+ " Euro";
         // opruimen vakken voor volgende artikel
         txtZoekArtNr.Text="";
         txtAantalArt.Text="";
         lblArtNaam.Text="";
         lblArtPrijs.Text="";
         lblSubTotaal.Text="";
         txtZoekArtNr.Focus();
      }
      private void verkocht()
      {
         MessageBox.Show(tekst,"Verkocht!");
         txtZoekNr.Text="";
         txtZoekNaam.Text="";
         lblKlantData.Text="";
         lstvTotaalVerkoop.Items.Clear();
         lstvVerkoop.Items.Clear();
         txtZoekNr.Focus();
      }
      #endregion
   }
}




В принцыпе ответ на вопрос, который я поставил в названии топика, я нашел.
Код: Выделить всё

int begin=vindpos;
int end=vindpos;
Duplicate(ref begin, ref end);

Ларчик как оказалось просто открывался. :oops:

Но вот, повторюсь, как я реализовал поиск дупликатов с одинаковой частью имени МНЕ НЕ НРАВИТЬСЯ!
Т.е. я понимаю что должна делать эта функция.
Она получает в качестве входных параметров позицию найденного элемента в отсортированном ArrayList и должна пошагово в двух направлениях сравнивать искомое со стоящим на следующей позиции.
Для сравнения нужно использовать Comparer. Он у нас есть в классе Persoon.
Но вот как это сравнение грамотно записать в коде while этой функции(см. первый пост)
я не знаю. :oops:

Всем наилучшие пожелания. И самые горячие поздравления с одним из самых любимых в народе Праздником 1 Мая!
Весенней солнечной и ТЕПЛОЙ погоды всем.


Вернуться в C#

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 17

    TopList