View Full Version : جستجو در Combobox
alaveh
شنبه 08 تیر 1392, 02:44 صبح
سلام
راهی هست که توی یک کمبوباکس دنبال یک مورد خاص گشت ولی با سرعت بالا ؟ یعنی مثلا زمان باز شدن فرم روی یک مورد خاص وایسته که لازمش داریم ولی نمیدونیم ItemIndex اون چنده .
البته مقدارهای موجود مرتب شده نیستن که بشه از روشهای جستجو مثل باینری یا ... استفاده کرد .
khorsandreza
شنبه 08 تیر 1392, 08:32 صبح
Combobox1.ItemIndex:= Combobox1.IndexOf('مقدار مورد جستجو');
alaveh
سه شنبه 11 تیر 1392, 00:57 صبح
Combobox1.ItemIndex:= Combobox1.IndexOf('مقدار مورد جستجو');
ممنون دوست عزیز
ولی IndexOf وجود نداره . ازش ایراد میگیره .
E2003 Undeclared identifier: IndexOf
alaveh
سه شنبه 11 تیر 1392, 01:10 صبح
ok
درست شد
اینجوریه :
Combobox1.ItemIndex:= Combobox1.Items.IndexOf('مقدار مورد جستجو');
یوسف زالی
سه شنبه 11 تیر 1392, 01:37 صبح
البته IndexOf تا جایی که من می دونم کنده. برای رسیدن به سرعت های خیلی بالا بهتره خودتون بازنویسیش کنید.
alaveh
جمعه 14 تیر 1392, 17:26 عصر
البته IndexOf تا جایی که من می دونم کنده. برای رسیدن به سرعت های خیلی بالا بهتره خودتون بازنویسیش کنید.
مثلا از چه روشی You-See (http://barnamenevis.org/member.php?70247-You-See) جان ؟
چون مرتب نیستند مقدارها و نمیشه هم مرتبشون کرد من هیچ روشی به ذهنم نمیرسه جز جستجوی خطی . اگر راهی هست خوشحال یشم بگی . هر چند مقدارهای موجود زیاد نیست که سرعتش تاثیری داشته باشه ولی بعدا به دردم یخوره .
یوسف زالی
جمعه 14 تیر 1392, 21:28 عصر
شاید به نظر منطقی نرسه ولی در برنامه من با جایگزین کردن این متد با متدی که خودم نوشتم سرعت این تیکه برنامه 2 برابر شد!
function IndexOf(List: TStrings; Value: string): integer;
var
i, id: integer;
begin
id := -1;
for i := 0 to List.Count -1 do
if SameText(Value, List[i]) then
begin
id := i;
break;
end;
Result := id;
end;
همون طور که می بینید این کد هم یک جستجوی خطی هست.
متد indexof در شی TStrings از CompareString استفاده می کنه.
اما در کد من از SameText که با اسمبلی پیاده شده استفاده شده.
نمی دونم، شاید در مواقعی وضعیت عکس بشه، همونطور که در روشهای سورت مشاهده می شه و هر سورتی برای یک تعدادی بهینه هست. مثلا سورت کوئیک برای تعداد کم اصلا توجیه نداره ولی خودش رو در تعداد بالا خیلی خوب نشون می ده.
به هر جهت همون طور که عرض کردم من با جایگزینی این متد تونستم سرعت اون تکه کدم رو تا 2 برابر افزایش بدم. ممکنه با پروسس های اسمبلی بتونید حتی به بالاتر از این روش دست پیدا کنید.
khorsandreza
یک شنبه 16 تیر 1392, 13:41 عصر
شاید به نظر منطقی نرسه ولی در برنامه من با جایگزین کردن این متد با متدی که خودم نوشتم سرعت این تیکه برنامه 2 برابر شد!
function IndexOf(List: TStrings; Value: string): integer;
var
i, id: integer;
begin
id := -1;
for i := 0 to List.Count -1 do
if SameText(Value, List[i]) then
begin
id := i;
break;
end;
Result := id;
end;
همون طور که می بینید این کد هم یک جستجوی خطی هست.
متد indexof در شی TStrings از CompareString استفاده می کنه.
اما در کد من از SameText که با اسمبلی پیاده شده استفاده شده.
نمی دونم، شاید در مواقعی وضعیت عکس بشه، همونطور که در روشهای سورت مشاهده می شه و هر سورتی برای یک تعدادی بهینه هست. مثلا سورت کوئیک برای تعداد کم اصلا توجیه نداره ولی خودش رو در تعداد بالا خیلی خوب نشون می ده.
به هر جهت همون طور که عرض کردم من با جایگزینی این متد تونستم سرعت اون تکه کدم رو تا 2 برابر افزایش بدم. ممکنه با پروسس های اسمبلی بتونید حتی به بالاتر از این روش دست پیدا کنید.
بنظر من سرعت کار بالا نرفته بلکه شما با استفاده از حلقه وقتی که به اولین مقدار می رسی از حلقه خارج میشوی اگر مورد جستجوی شما آخرین اندیکس باشد از خود IndexOff زمان بیشنری را طلب خواهد کرد حال اگر در اولین اندیکس مورد جستجوی شما باشد سریعتر خواهد بود
یوسف زالی
یک شنبه 16 تیر 1392, 14:05 عصر
بنظر من سرعت کار بالا نرفته
شما تست کردی عزیزم؟
می دونی تفاوت استفاده از SameText و API CompareString در چی هست دوست من؟
ربطی به استفاده از Break نداره. در حقیقت کد تقریبا کپی کد IndexOf پیش فرضه. دلیل افزایش سرعت استفاده نکردن از API هست.
شما تست کن، تعداد مثلا 1000 خط رو در یک لیست 1000 بار پشت سر هم سرچ کن، با هر دو کد، متوجه می شی منظور من رو.
khorsandreza
یک شنبه 16 تیر 1392, 14:30 عصر
ببین دوست عزیز من از همین روش شما قبلا برای یک کاری استفاد کردم اگه انتشار می دادم می گفتم کار خودم هست و کار شما را تفلید کار خودم تلقی می کردم حال شما از همان شیوه استفاده کرده در یک اطلاعات محدود قابل قبول است ولی این کار در داده های زیاد کند کار می کند و بروی کامپوننت های خود دلفی Raize و TMS تست کردام
بنده قصد جسارت به کار شما را نداشتم از اینکه اگه باعث تاراحتی شما شدم پوزش می خواهم
یوسف زالی
یک شنبه 16 تیر 1392, 15:24 عصر
نه عزیزم ناراحت نشدم. از این متعجب شدم که بحث روی تابع مقایسه بود ولی شما متوجه Break شدید و اساس کار رو اشتباه گرفتید.
با جایگزین کردن این متد با متدی که خودم نوشتم
هرگز هم نگفتم به به عجب کار بزرگی کردم. فقط گشتم دیدم که کنده. درستش کردم. همین. خب خودم نوشتمش دیگه :لبخند:
ممکنه کد شما خیلی از کد من بهتر کار کنه.
برای یادگیری، نباید موضع داشت.
نظر خود ماست که ما رو پیش می بره.
در یک اطلاعات محدود قابل قبول است ولی این کار در داده های زیاد کند کار می کند
اتفاقا روی داده های میلیونی تست گرفتم و داره کار می کنه و اتفاقا خیلی هم سریع تره.
گزارشات پایوت من بر اساس همین کد بسیار تندتر شده.
در کل کار با رشته ها وقتی به سمت اسمبلی نزدیک تر می شه در داده های خیلی خیلی زیاد خودش رو نشون می ده..
من باید پیاده سازی اون کامپوننت ها رو بخونم تا ببینم شاید داره از روش دیگه ای که تند تر هست استفاده می کنه یا ...
در کل منظوری نداشتم، فقط راه حلی ارائه دادم که داره روی سیستم مشتریان من بازدهی بالاتری نسبت به IndexOf می ده. به طور دقیق بالای 85 درصد بهبود سرعت.
اگر کد بهتری دارید خوشحال می شم ازش استفاده کنم و کد خودم رو کنار بگذارم.
موفق باشید.
khorsandreza
یک شنبه 16 تیر 1392, 15:38 عصر
من از اینگار برای حدود 150 هزار رکورد می خواستم استفاده کنم با انکه بصورت مرتب شده بود نشد خیلی کند بود کارم را با روش دیگری انجام دادم (حتما کدهای شما را تست میکنم) اگر بر روی یک میلیون رکورد پاسخ بدهد موضوع جالبی است
developing
پنج شنبه 27 تیر 1392, 11:54 صبح
با سلام
اول اینکه: جناب یوسف خان من کد شما رو امتحان کردم از IndexOf خود دلفی خیلی سریعتر بود. (البته دلفی من 2009 هست)
پروژه رو پیوست کردم شما هم امتحان کنید.
107465
دوم : اگه داده های شما مرتب شده اند می تونید از جستجوی دودویی استفاده کنید که مشکل حل بشه. می تونید از تابع زیر استفاده کنید.(باز هم تذکر می دم این تابع برای لیست های مرتب کار می کنه.)
function IndexOf(List: TStrings; Value: string): integer;
var
id: integer;
l, h, m: Integer;
begin
id := -1;
l := 0;
h := List.Count - 1;
while l <= h do
begin
m := (h + l) div 2;
if SameText(Value, List[m]) then
begin
id := m;
break;
end
else if value > List[m] then
l := m + 1
else if value < list[m] then
h := m - 1;
end;
Result := id;
end;
یوسف زالی
پنج شنبه 27 تیر 1392, 18:26 عصر
در اين باره سرچ کردم:
http://www.delphipages.com/forum/showthread.php?t=204185
کد شما رو هم ديدم. در نمونه شما کد من خيلي کند تر هست. اما در نمونه هايي که من در برنامم دارم خيلي سريعتره!!
اين مساله گويا به چيزهاي زيادي ربط داره، مثلا طول رشته اي که داريم مي گرديم، استفاده کردن يا نکردن از کاراکتر هاي خاص، ...
براي مثال اين فايل رو ببينيد، يکي از فايلهايي هست که برنامه من توليد مي کنه، در اين نمونه جستجو به روش من سريع تره.
http://wdl.persiangig.com/pages/download/?dl=http://yousijoon.persiangig.com/Zip/a.rar
همونطور که گفتم برای هر کاربردی بهینه نیست. مثل همون کوئیک سرچ.
khorsandreza
سه شنبه 01 مرداد 1392, 03:00 صبح
در اين باره سرچ کردم:
http://www.delphipages.com/forum/showthread.php?t=204185
کد شما رو هم ديدم. در نمونه شما کد من خيلي کند تر هست. اما در نمونه هايي که من در برنامم دارم خيلي سريعتره!!
اين مساله گويا به چيزهاي زيادي ربط داره، مثلا طول رشته اي که داريم مي گرديم، استفاده کردن يا نکردن از کاراکتر هاي خاص، ...
براي مثال اين فايل رو ببينيد، يکي از فايلهايي هست که برنامه من توليد مي کنه، در اين نمونه جستجو به روش من سريع تره.
http://wdl.persiangig.com/pages/download/?dl=http://yousijoon.persiangig.com/Zip/a.rar
همونطور که گفتم برای هر کاربردی بهینه نیست. مثل همون کوئیک سرچ.
سلام
این تاپیک را تقیب می کردم و مثال ها را تست روش شما نسبت به روش دوست developing در رشته های با طول بیش از 25 کاراکتر سریعتر عمل می کنه ولی یک اشکالی که در این کار هست به نظر من روش بارگذاری اطلاعات داخل لیست است که در اطلاعات حجیم زمان زیادی را می بره اگه بشه این شیوه را طوری تغییر داد که بار گذاری در داخل لیست سریعتر بشه و یا مثل صفحات گوگل و ... مستقیم از دیتا بیس بخونه و مقادیر مشابه را نشان بده.
من متد شما در برنامه کار بردی دارم استفاده می کنم ولی مشکل همین پر کردن لیست باکس است
یوسف زالی
سه شنبه 01 مرداد 1392, 07:27 صبح
منظورتون از پر کردن چیه؟
text := SomeThings
یا Add ؟
بارگذاری در StringList سرعت خوبی داره، اما در انتقال به شی ListBox کند می شه اون هم به دلیل رفرش شدن ها و مسایل نمایشی کند می شه.
فکر کنم می تونیم این کار رو مرحله ای و بدون رفرش انجام بدیم. در حقیقت مثل مکش داده در ClientDataSet می شه این کار رو Packet به Packet انجام داد و یوزر متوجه لود شدن اون در پشت داستان نشه. اما اگر منظورتون خود TStringList باشه، مثال بزنید.
khorsandreza
سه شنبه 01 مرداد 1392, 16:39 عصر
منظورتون از پر کردن چیه؟
text := SomeThings
یا Add ؟
بارگذاری در StringList سرعت خوبی داره، اما در انتقال به شی ListBox کند می شه اون هم به دلیل رفرش شدن ها و مسایل نمایشی کند می شه.
فکر کنم می تونیم این کار رو مرحله ای و بدون رفرش انجام بدیم. در حقیقت مثل مکش داده در ClientDataSet می شه این کار رو Packet به Packet انجام داد و یوزر متوجه لود شدن اون در پشت داستان نشه. اما اگر منظورتون خود TStringList باشه، مثال بزنید.
نه دقیقا بخش دوم که خودتان فرموذید بصور ت Packet انجام بگیره بیشتر سختی کار در بخش نمایش اتفاق می افته که کاربردر گیرش هست .
یوسف زالی
شنبه 05 مرداد 1392, 05:40 صبح
function TListBoxStrings.Add(const S: string): Integer;
begin
Result := -1;
if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then exit;
Result := SendMessage(ListBox.Handle, LB_ADDSTRING, 0, Longint(PChar(S)));
if Result < 0 then raise EOutOfResources.Create(SInsertLineError);
end;
اون ارسال مسیج کار رو خراب کرده، برداشتنش هم کار ما رو خراب می کنه.
فکر می کنم تنها راه همون پکت پکت کردن باشه.
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.