مشکل در برنامه ای که تعداد تکرار تک تک کلمات را میشمارد؟ - هفت خط کد انجمن پرسش و پاسخ برنامه نویسی

مشکل در برنامه ای که تعداد تکرار تک تک کلمات را میشمارد؟

+1 امتیاز
با سلام , دوستان من کد برنامه ای رو می خوام که اول یک فایل متنی رو باز کنه بعد تمام نوشته های فایل رو توی خروجی چاپ کنه و بعد تعداد تکرار تک تک کلمات رو هم توی خروجی نمایش بده ممنون میشم کد برنامرو برام بنویسید لطفا در محیط کنسول باشه. خیلی ممنون.
سوال شده اسفند 16, 1392  بوسیله ی daniyaltjm (امتیاز 840)   47 88 103
دوباره تگ گذاری شد تیر 16, 1393 بوسیله ی BlueBlade
نه ببخشید منظور من تعداد تکرار تک تک کلمات هست مثلا اگه is صد بار تکرار شده توی خروجی نشون بده. ممنون

2 پاسخ

+3 امتیاز
 
بهترین پاسخ

سلام.

علاوه بر کدی که امید قرار داد، می تونید کد زیر رو هم تست کنید (یه کم حالات بیشتری رو در نظر می گیره) :

Dictionary<string, int> mydic = new Dictionary<string, int>();
            StreamReader sr = new StreamReader("d:\\test2.txt");
            string AllChar = sr.ReadToEnd();
            sr.Close();
            char[] a = new char[]{' ', '.',',','!', '?', '\n','\r'};
            string[] records = AllChar.Split(a);
            for (int i = 0; i < records.Length; i++)
            {
                if (!string.IsNullOrWhiteSpace(records[i]))
                {
                    if (mydic.ContainsKey(records[i]))
                    {
                        mydic[records[i]]++;
                    }
                    else
                    {
                        mydic.Add(records[i], 1);
                    }
                }
            }
            foreach (var result in mydic)
            {
                Console.Write(string.Format("repeat {0} for word {1}\n", result.Value, result.Key));
            }
    Console.ReadKey();

 

اگر نمی خواید از دیکشنری استفاده کنید و قصد استفاده از آرایه ها رو دارید، باید اینو دقت کنید که با آرایه های معمولی گرچه میشه انجامش داد ولی ایرادی که داره اینه که آرایه ها از یک جنس هستن در صورتیکه شما باید ترکیبی از نوع داده ای رشته (کلمات) و نوع int (تکرار هر کلمه) رو داشته باشید. راهی که به نظر من میرسه اینه که آرایه دو بعدی رشته ای در نظر بگیرید و موقع افزودن به مقدار تکرار هر کلمه، ابتدا اونو به عدد تبدیل کنید و بعدش بهش یکی اضافه کنید و دوباره بصورت رشته ای ذخیره کنیدش. بذارید کدها رو بذارم و روی کدها توضیحات رو بگم تا راحت تر متوجه بشید :

StreamReader sr = new StreamReader("d:\\test2.txt");
            string AllChar = sr.ReadToEnd();
            sr.Close();
            char[] a = new char[]{' ', '.',',','!', '?', '\n','\r'};
            string[] records = AllChar.Split(a);
            string[][] myresult = new string[records.Length][];
            for (int k = 0; k < records.Length; k++)
                {
                        myresult[k] = new string[2];
                        myresult[k][0] = string.Empty;
                        myresult[k][1] = "0";
                }
            for (int i = 0; i < records.Length; i++)
            {
                if (!string.IsNullOrWhiteSpace(records[i]))
                {
                    for (int j = 0; j < myresult.Length; j++)
                    {
                        if (!string.IsNullOrWhiteSpace(myresult[j][0]))
                        {
                            if (records[i].Trim() == myresult[j][0])
                            {
                                myresult[j][1] = (Convert.ToInt32(myresult[j][1]) + 1).ToString();
                                break;
                            } 
                        }
                         else 
                            {
                                myresult[j][0] = records[i];
                                myresult[j][1] = "1";
                                break;
                            }
                    }
                }
            }
            for (int i = 0; i < myresult.Length; i++)
            {
                if(!string.IsNullOrWhiteSpace(myresult[i][0]))
                Console.WriteLine(string.Format("repeat {0} for word {1}", myresult[i][1], myresult[i][0]));
            }
Console.ReadKey();

من در این روش از Jagged Array ها استفاده کردم. این نوع آرایه ها رو خانه هایی فرض کنید که درون هر خانه خودش یک آرایه دیگه وجود داره. چون ما با عبارات دو مقداری (کلمه و تکرار کلمه) سر و کار داریم، هر خانه این آرایه رو کلمه ای در نظر بگیرید که شامل دو مقدار هست. یکی خود کلمه و دیگری تعداد تکرارش.

در گام بعدی من به تعداد کلمات فایلمون اومدم خونه برای jagged array مورد نظرمون new کردم و این خونه ها رو بصورت پیش فرض متن کلمات رو برابر خالی (Empty ) و تعداد تکرار 0 قرار دادم.

حالا باید کلمات فایل مورد نظر که درون records قرار دارند  رو با اعداد موجود در jagged array مقایسه کنیم. یعنی یک حلقه for داخلی خواهیم داشت که حداکثر به تعداد خانه های آرایه باید با کلمات فایلمون مقایسه بشه. در زمان مقایسه کلمات فایل با کلمات موجود در آرایه ممکنه 2 حالت پیش بیاد. یا کلمه موجود در فایل قبلا در آرایه ذخیره شده، در اینصورت به تعداد اون یکی اضافه میشه و از break برای خروج از حلقه استفاده شده. یا اینکه اون کلمه ثبت نشده و یک کلمه جدید هستش که در اینصورت کلمه درج میشه و تعداد تکرار 1 هم براش در نظر گرفته میشه و دوباره از break برای خروج از حلقه استفاده شده.

در حلقه for ای هم که برای چاپ آرایه در نظر گرفتم فقط کلماتی چاپ شدن که empty نباشن.

من این روش رو توصیه نمی کنم. چون هم درکش یه خورده مشکله و هم اینکه واقعا راه بهینه ای نیست. ولی بهرحال امیدوارم کار شما رو راه بندازه.

موفق باشید.

پاسخ داده شده اسفند 16, 1392 بوسیله ی veniz2008 (امتیاز 2,083)   1 5 21
ویرایش شده اسفند 16, 1392 بوسیله ی veniz2008
ممنون که زحمت کشیدین , لطفا در مورد این کد:Dictionary<string, int> mydic = new Dictionary<string, int>(); و این  if (!string.IsNullOrWhiteSpace(records[i]))
                {
                    if (mydic.ContainsKey(records[i]))
                    {
                        mydic[records[i]]++;
                    }
                    else
                    {
                        mydic.Add(records[i], 1);
                    }  توضیح بدین من نمی فهمم.
سلام.
روند کار بسیار ساده هست.
در ابتدا محتوای فایل رو با استفاده از کلاس streamReader خوندیم.
در ادامه باید کلماتی رو که از فایل خوندیم برای شمارش کردن، از هم تفکیک کنیم.
برای تفکیک کلمات چند حالت کلی وجود داره. یا بین کلمات فاصله (space) هست یا بینشون نقطه هست،ممکنه بین کلمات کاما یا علامت تعجب باشه. یه حالت دیگه ممکنه آخر کلمه علامت سوال باشه، همچنین ممکنه بین یک کلمه و کلمه دیگه از کاراکترهای اینتر استفاده شده باشه. من سعی کردم این حالات رو برای جدا کردن کلمات در یک آرایه کاراکتری در نظر بگیرم.اگر موردی از قلم افتاده می تونید خودتون اونو اضافه کنید.
در ادامه در یک حلقه for که به تعداد کلمات تکرار میشه، ابتدا چک می کنم که اون کلمه یک space نباشه.چون space یک کلمه نیست و نباید درون دیکشنری ثبت بشه.
متد IsNullOrWhiteSpace این کار رو برای من انجام میده.
در ادامه از یک شی جنریک به نام Dictionary استفاده کردم. این شی از دو قسمت تشکیل شده. کلید و مقدار.
بخش کلید (Key) منحصر بفرد هست و نمی تونه مقدار تکراری داشته باشه و بخش مقدار (value) یک ارزش رو برای کلید نگهداری میکنه. من کلمات رو بعنوان کلید در نظر گرفتم (کلمات از جنس string هستن) و تعداد تکرار هر کلمه رو هم بعنوان value در نظر گرفتم که از جنس int خواهد بود.
اینطوری متوجه میشم هر کلمه چند بار تکرار میشه.
در if و else داخلی چک می کنم آیا اون کلمه قبلا درون دیکشنری ثبت شده یا نه. اگر ثبت شده بود (شرط if) به مقدار value یکی اضافه می کنم و اگر کلمه مورد نظر جدید بود (بخش else) کلمه جدید و مقدار تکرار 1 رو براش ثبت میکنم.
امیدوارم کامل متوجه شده باشید.
موفق باشید.
خیلی ممنون برنامت خیلی کامل بود ولی اگر بخوایم با آرایه معمولی این برنامرو بنویسیم چطور؟ و یک نکته دیگه اینکه اول برنامه باید کل فایل رو تو خروجی چاپ کنه و بعد بشماره.
دستتون درد نکنه خیلی جالب توضیح دادین . آره کاملا مشخصه که الگوریتم اولی شما بهتر هست فقط خواستم بدونم که چطوری میشه انجامش داد . سپاس گذارم.
+2 امتیاز
            String fileLocation = "D:\\file.txt";
            var counts = new Dictionary<string, int>();
            using (StreamReader stream = new StreamReader(fileLocation))
            {
                string[] words = stream.ReadToEnd().Split();
                for (int i = 0; i < words.Length; i++)
                {
                    int val;
                    if (!counts.TryGetValue(words[i], out val))
                        counts[words[i]] = 1;
                    else
                        counts[words[i]] = ++val;
                }
                
            }

            foreach (var item in counts)
            {
                var word = item.Key;
                var count = item.Value;
                Console.WriteLine(word + "   " + count);
            }

 

پاسخ داده شده اسفند 16, 1392 بوسیله ی BlueBlade (امتیاز 15,315)   15 18 89
...