zoukankan      html  css  js  c++  java
  • 以大数据眼光欣赏唐人文墨(二)代码实现

    Begin

    继上次对唐诗三百首和全唐诗四万多首诗进行分析之后…

    详细内容可以看看上次这篇文章,《以大数据眼光欣赏唐人文墨(一)》

    这篇文章来讲讲具体的代码实现,本项目全部采用C#编写。

    软件介绍

    首先为了做本次分析,我用C#写了一个Winform程序,名字很逗比,叫做“我爱读诗词——唐诗”。

    软件和唐诗三百首数据文件打包下载:http://pan.baidu.com/s/1gftDKTd

    全唐诗数据由于太大了需要下载的同学点这个:http://pan.baidu.com/s/1nv4WNNF

    下面是软件截图:

    启动直接写成控制台的,反正就是自己用而已,粗糙一点无所谓,能用就行。

    唐诗三百首匹配界面截图:

    这里是从源文件读取数据并整理出每一首诗的标题、作者、内容。

    全唐诗的匹配的界面:

    你问我为什么这个的背景是深色的,我也不知道(摊手,反正当时就这么设置了= =…

    由于全唐诗太多了,要打开并分析出来需要很长时间,所以这里用了小容量样本。

    分析界面:

    这个就是上次的文章里展示的,主要功能都在这里了。窗口主体是一个listview控件,用来分类显示分析结果。

    代码

    关于从源文件整理出标题、作者、内容的代码,请参见  用C#学习唐诗三百首和全唐诗

    标题分析

    首先是从数据文件里读取出每一首诗

    QData qD = new QData(poemFile);

    定义一个 Dictionary<string, int> 结构,索引是标题,值是数量。
    分析很简单,从QData对象读取出所有的标题然后判断是否在 Dictionary<string, int> 存在这个标题,如果存在数量就+1,如果不存在就添加进去。
    代码如下:

    string[] sections = qD.GetAllSectionsArray();
    Console.WriteLine("共有[{0}]首诗", sections.Length);
    foreach (string s in sections)
    {
        Application.DoEvents();
        string title = qD.GetValue(s, "Title");
        this.lblStatus.Text = (++count).ToString();
        if (title.Length > 0)
        {
            if (poemTitle.ContainsKey(title))
                poemTitle[title]++;
            else
                poemTitle.Add(title, 1);
        }
    }

    然后再对 Dictionary<string, int>  排序:

    var poemTitleSorted = from pObj in poemTitle orderby pObj.Value descending select pObj;

    Linq语句用起来太方便了。
    然后把排序的结果添加到Listview就OK了~

    作者分析

    和标题分析是大同小异的,这里不再累述。

    单字分析

    先贴出代码了,思路很简单,就是提取出所有内容,拆分出每个字,再去掉标点符号,和标题分析一样进行统计。

    Dictionary<char, int> poemChar = new Dictionary<char, int>();
    string poemFile = this.txtFile.Text;
    QData qD = new QData(poemFile);
    int count = 0;
    long charCount = 0;
    if (File.Exists(poemFile))
    {
        string[] sections = qD.GetAllSectionsArray();
        Console.WriteLine("共有[{0}]首诗", sections.Length);
        foreach (string s in sections)
        {
            Application.DoEvents();
            string content = qD.GetValue(s, "Content");
            this.lblStatus.Text = (++count).ToString();
            charCount += content.Length;
    
            foreach (char c in content)
            {
                if (poemChar.ContainsKey(c))
                    poemChar[c]++;
                else
                    poemChar.Add(c, 1);
            }
        }
    
        Console.WriteLine("共有[{0}]字", charCount);
    
        if (poemChar.ContainsKey(''))
            poemChar.Remove('');
        if (poemChar.ContainsKey(''))
            poemChar.Remove('');
        if (poemChar.ContainsKey(''))
            poemChar.Remove('');
        if (poemChar.ContainsKey(''))
            poemChar.Remove('');
        if (poemChar.ContainsKey('['))
            poemChar.Remove('[');
        if (poemChar.ContainsKey(']'))
            poemChar.Remove(']');
        if (poemChar.ContainsKey('-'))
            poemChar.Remove('-');
    
        Console.WriteLine("去除重复之后共有 {0} 字", poemChar.Count);
    
        var poemTitleSorted = from pObj in poemChar orderby pObj.Value descending select pObj;  //Linq排序
    
        this.listView.Clear();
        this.listView.Columns.Add("单字", 200);
        this.listView.Columns.Add("单字数量", 100);
        this.listView.Columns.Add("比例", 100);
        this.listView.BeginUpdate();
        foreach (KeyValuePair<char, int> p in poemTitleSorted)
        {
            double ratio = (double)p.Value / (double)charCount * 100;
            ListViewItem item = new ListViewItem(new string[] { p.Key.ToString(), p.Value.ToString(), ratio.ToString("F5") + "%" });
            this.listView.Items.Add(item);
        }
        this.listView.EndUpdate();
    }
    qD.Close();

    诗句长度分析

    一样贴出代码。思路是提取每首诗的内容之后,按标点符号拆分,我这里针对逗号、句号、问号和感叹号拆分,然后就能获取每个诗句的长度了。用Linq排个序就好了。

    string poemFile = this.txtFile.Text;
    Dictionary<string, int> poemType = new Dictionary<string, int>();
    QData qD = new QData(poemFile);
    int count = 0;
    
    if (File.Exists(poemFile))
    {
        string[] sections = qD.GetAllSectionsArray();
        Console.WriteLine("共有[{0}]首诗", sections.Length);
        foreach (string s in sections)
        {
            Application.DoEvents();
            string content = qD.GetValue(s, "Content");
            this.lblStatus.Text = (++count).ToString();
    
            int comma = content.IndexOf('');
            int period = content.IndexOf('');
            int questionMark = content.IndexOf('');
            int exclamationPoint = content.IndexOf('');
    
            comma = comma < 0 ? (period < 0 ? (questionMark < 0 ? exclamationPoint : questionMark) : period) : comma;
            period = period < 0 ? comma : period;
            questionMark = questionMark < 0 ? comma : questionMark;
            exclamationPoint = exclamationPoint < 0 ? comma : exclamationPoint;
    
            int min = comma < period ? comma : period;
            min = min < questionMark ? min : questionMark;
            min = min < exclamationPoint ? min : exclamationPoint;
            min = min < 0 ? 0 : min;
    
            string wordsOfFirst = content.Substring(0, min).Length.ToString();
    
            content = NumberToChinese(wordsOfFirst) + "";
            if (content.Length > 0)
            {
                if (poemType.ContainsKey(content))
                    poemType[content]++;
                else
                    poemType.Add(content, 1);
            }
        }
    }
    
    var poemTitleSorted = from pObj in poemType orderby pObj.Value descending select pObj;  //Linq排序
    
    this.listView.Clear();
    this.listView.Columns.Add("句子长度", 200);
    this.listView.Columns.Add("数量", 100);
    this.listView.Columns.Add("比例", 100);
    this.listView.BeginUpdate();
    foreach (KeyValuePair<string, int> p in poemTitleSorted)
    {
        double ratio = (double)p.Value / (double)count * 100;
        ListViewItem item = new ListViewItem(new string[] { p.Key, p.Value.ToString(), ratio.ToString("F4") + "%" });
        this.listView.Items.Add(item);
    }
    this.listView.EndUpdate();
    qD.Close();

    End

    实现的核心代码基本就这些了,没有多少代码,我对C#不是很熟悉,代码写得比较冗长,请大家多多指教。

    我的微信公众号:DealiAxy

  • 相关阅读:
    在.net C#里怎样调用非托管动态库函数dll?
    Visual C#中的MDI编程
    c#图形装置接口
    粗糙集理论介绍
    Using .NET DataSet in Flex 2
    图象光照研究路线
    基于光照模型应用前景
    使用netsh.exe配置TCP/IP
    vb.net 防止MDI子窗体被多次实例化的四种方法
    一定概率选中某一字母
  • 原文地址:https://www.cnblogs.com/deali/p/6670496.html
Copyright © 2011-2022 走看看