Hello World
Spiga

从CSDN的趣味题学C# 3.0

2009-02-01 10:43 by 老赵, 13587 visits

引文参见:从CSDN的趣味题学Python

两道算法趣味题:

  1. 要求算一任意长度字符串中不同的字符以及它的个数。
  2. 把一段字符串用“右起竖排”的古文格式输出。

引文用了Python来解这种趣味题,很有意思,Python也很适合。不过我看了看似乎这篇文章没有真正理解如今的C#可以怎么用,老赵一时兴起,也来设法做了一下。

第1题

Python版:

dic = {}
for s in "abcdefgabc":
    dic[s] = 1 if s not in dic else (dic[s]+1)
print '\n'.join('%s,%s' % (k, v) for k, v in dic.items())

C# 3.0版

var values = "abcdefgabc"
    .GroupBy(c => c)
    .Select(g => String.Format("{0}, {1}", g.Key, g.Count()))
    .ToArray();
Array.ForEach(values, v => Console.WriteLine(v));

如果加上一个扩展——不写出来了,大家应该一看便知,老赵强烈推荐大家在项目中都要加上合适的扩展——再减少点行数:

"abcdefgabc"
    .GroupBy(c => c)
    .ForEach(v => Console.WriteLine(g.Key + ", " + g.Count()));

或者用上“狭义”LINQ?

string text = "abcdefgabc";
var result = from c in text group c by c into g select g;
foreach g in result Console.WriteLine(g.Key + "," + g.Count());

第2题

Python版:

def main(offset=6):
    string = u'静夜思 李白床前明月光,疑似地上霜。举头望明月,低头思故乡。090131'
    a = [[' ']*offset for row in xrange(offset)]
    for i in xrange(offset):
        for j in xrange(offset):
            a[i][j] = string[j + i*offset]
    b = [[r[col] for r in a[::-1]] for col in xrange(len(a[0]))]
    print '\n'.join([u'┊'.join(unicode(c) for c in row)for row in b])

C# 3.0版:

static void Print(string text, int offset)
{
    var matrix = text
        .Select((c, i) => new { Char = c, Index = i })
        .GroupBy(c => c.Index % offset, c => c.Char.ToString());
    Array.ForEach(
        matrix.ToArray(),
        a => Console.WriteLine(String.Join("|", a.Reverse().ToArray())));
}

C# 3.0扩展版:

static void Print(string text, int offset)
{
    text
        .Select((c, i) => new { Char = c, Index = i })
        .GroupBy(c => c.Index % offset, c => c)
        .ForEach(g => Console.WriteLine(g.Reverse().Join("|")));
}

调用一下:

Print("床前明月光疑似地上霜举头望明月低头思故乡", 5);

结果:

低|举|疑|床
头|头|似|前
思|望|地|明
故|明|上|月
乡|月|霜|光

最后声明一下,本文并非为了挑起语言之争。Python是一门强大灵活的语言,学习Python有百利而无一害。Python还有一个好处,那就是代码格式,至少缩进会非常的规范——没办法,在Python中缩进是语法的一部分,缩进不对直接导致代码运行不通过。代码格式一直不佳的朋友们可以尝试一下。

希望大家在掌握一门工具时把它用活,用好。C# 3.0中的高级特性更是大大提高开发效率的重要工具。其实这种“趣味编程”最关键的是“语言特性”,“语法”而不是其中包含的类库功能。其实Java也有内联写法,可以写的很短,说Java要20行以上——那只是不知道怎么“活用”Java而已。

最后,再附赠一个C#趣味编程。大家猜猜下面的代码输出什么?(暂时找不到了,一会儿补上)

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

47 条回复

  1. JimLiu
    *.*.*.*
    链接

    JimLiu 2009-02-01 10:53:00

    最后一句话是无厘头吗?呵呵

  2. TaranChen
    *.*.*.*
    链接

    TaranChen 2009-02-01 10:54:00

    老赵太逗了!!!!

  3. 老赵
    admin
    链接

    老赵 2009-02-01 10:55:00

    --引用--------------------------------------------------
    JimLiu: 最后一句话是无厘头吗?呵呵
    --------------------------------------------------------
    不是,真找不到了,在找

  4. kkun
    *.*.*.*
    链接

    kkun 2009-02-01 11:07:00

    赵老师能否简单介绍下Python的应用范围?感激不尽,
    对它有所了解,但一直不知何时何地使用之,能做些什么,或者说是应用场合

  5. 阿牛
    *.*.*.*
    链接

    阿牛 2009-02-01 11:10:00

    .Select(p => String.Format("{0}, {1}", g.Key, g.Count()))
    这里写错了吧?

  6. 小伦
    *.*.*.*
    链接

    小伦 2009-02-01 11:19:00

    好玩~~

  7. 老赵
    admin
    链接

    老赵 2009-02-01 11:20:00

    @阿牛
    是,变量名应该是g

  8. Anders Liu
    *.*.*.*
    链接

    Anders Liu 2009-02-01 11:37:00

    嗯!附赠的这个趣味题很有趣!!

  9. 老赵
    admin
    链接

    老赵 2009-02-01 11:45:00

    --引用--------------------------------------------------
    Anders Liu: 嗯!附赠的这个趣味题很有趣!!
    --------------------------------------------------------
    这都被你发现了

  10. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-02-01 13:20:00

    VB9,无扩展单行版

    Enumerable.ToList( _

  11. 老赵
    admin
    链接

    老赵 2009-02-01 13:37:00

    @装配脑袋
    ForEach是哪个方法?

  12. xjb
    *.*.*.*
    链接

    xjb 2009-02-01 13:37:00

    嘿嘿,有趣

  13. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-02-01 13:38:00

    @Jeffrey Zhao
    呵呵,是List(Of T)的实例方法

  14. 老赵
    admin
    链接

    老赵 2009-02-01 13:40:00

    @装配脑袋
    嘿,原来List<T>有ForEach方法呀

  15. 重典
    *.*.*.*
    链接

    重典 2009-02-01 13:46:00

    下面自动输出了一堆评论

  16. DiryBoy
    *.*.*.*
    链接

    DiryBoy 2009-02-01 13:48:00

    linq很厉害……但是第2题好像没有考虑字符串长不能整除offset的情况吧?

  17. 老赵
    admin
    链接

    老赵 2009-02-01 14:43:00

    @DiryBoy
    嗯,只涉及输入正常的情况

  18. 阿牛
    *.*.*.*
    链接

    阿牛 2009-02-01 14:47:00

    刚才求证了一下,才知道原来楼主是直接手写的代码吧,厉害。

    不过,第二道题也是这样才能编译过去,不知道是不是我的IDE的原因:
    static void Print(string text, int offset)
    {
    text
    .Select((c, i) => new { Char = c, Index = i })
    .GroupBy(c => c.Index % offset, c => c.Char.ToString()).ToList()
    .ForEach(g => Console.WriteLine(string.Join("|",g.Reverse().ToArray())));
    }

  19. 不好意思[未注册用户]
    *.*.*.*
    链接

    不好意思[未注册用户] 2009-02-01 14:59:00

    不好意思,"大家一看便知的扩展"是什么?

  20. 老赵
    admin
    链接

    老赵 2009-02-01 15:01:00

    @不好意思
    自己想一想,试验一下吧

  21. 老赵
    admin
    链接

    老赵 2009-02-01 15:01:00

    @阿牛
    不是说了是“C# 3.0扩展版”吗?呵呵,要加上简单的常用扩展才行。

  22. 不好意思[未注册用户]
    *.*.*.*
    链接

    不好意思[未注册用户] 2009-02-01 16:06:00

    您的意思不是说自己写一个IEnumerable<T>的扩展吧?

  23. 老赵
    admin
    链接

    老赵 2009-02-01 16:23:00

    --引用--------------------------------------------------
    不好意思: 您的意思不是说自己写一个IEnumerable&lt;T&gt;的扩展吧?
    --------------------------------------------------------
    没错,自己写

  24. ChuPaChuPs[未注册用户]
    *.*.*.*
    链接

    ChuPaChuPs[未注册用户] 2009-02-01 17:30:00

    李白床前明月光疑似地上霜举头望明月低头思故乡

    输出是
    故|明|上|月|李
    乡|月|霜|光|白
    低|举|疑|床
    头|头|似|前
    思|望|地|明

    这不对吧,应该是
    故|明|上|月|李
    乡|月|霜|光|白
    低|举|疑|床
    头|头|似|前
    思|望|地|明

  25. ChuPaChuPs[未注册用户]
    *.*.*.*
    链接

    ChuPaChuPs[未注册用户] 2009-02-01 17:31:00

    故|明|上|月|李
    乡|月|霜|光|白
    低|举|疑|床
    头|头|似|前
    思|望|地|明

  26. ChuPaChuPs[未注册用户]
    *.*.*.*
    链接

    ChuPaChuPs[未注册用户] 2009-02-01 17:32:00

    为什么不能用空格开头~~~

  27. 老赵
    admin
    链接

    老赵 2009-02-01 17:41:00

    @ChuPaChuPs
    不是用不用空格开头,而是程序只考虑了正确输入。
    趣味编程,不考虑太多。

  28. overred
    *.*.*.*
    链接

    overred 2009-02-01 17:51:00

    最后一句的输出是:
    (暂时找不到了,一会儿补上)

  29. 徐少侠
    *.*.*.*
    链接

    徐少侠 2009-02-01 21:39:00

    我的感觉是大家要好好学习了

    目前的编码风格已经开始发生一些革命性的东西

    我也不能很清晰得来总结

    但是一个直观的感觉就是很多for循环开始消失了

    以前有了设计模式以后,很多代码里的if语句已经不见了。
    甚至造成“你今天if了吗”的调侃(决策的逻辑很多都由多态完成了)

    随着面向对象的不断深入,以前过程化时代形成的编码风格和思维方式正遭受有力的冲击

    泛型、匿名方法、Linq、WWF、WPF、WCF......

    微软又一次将我们的编程世界进行了一次“封装”

    结果就是很多我们现在熟悉的东西未来可能就要成为“底层技术”、“核心技术”

    而日常编码的东西则变成了新的体系和结构

    多数程序员又一次要工作在更高的抽象层次上,离硬件和操作系统更远了




  30. Bēniaǒ
    *.*.*.*
    链接

    Bēniaǒ 2009-02-01 22:16:00

    ^.^ 新年过后的第一回复。学习了。

  31. 老赵
    admin
    链接

    老赵 2009-02-01 23:28:00

    @徐少侠
    其实这些东西在函数式编程或动态语言上已经类似实现了,语言是结合演变的

  32. 毁于随
    *.*.*.*
    链接

    毁于随 2009-02-02 08:58:00

    Linq..还没有学到.目前还看不太懂.又落伍了.

  33. 徐少侠
    *.*.*.*
    链接

    徐少侠 2009-02-02 10:01:00

    @Jeffrey Zhao
    是的。我的意思就是说以后直接思考数组、集合等遍历的东西会逐渐少了

    编码的思维方式会有所变化的

  34. 老赵
    admin
    链接

    老赵 2009-02-02 10:20:00

    @徐少侠
    嗯嗯,C# 3.0里可都是nb货,一些人叫着“不纯粹”“没有用”,真是为他们可惜。

  35. 悟〈--觉
    *.*.*.*
    链接

    悟〈--觉 2009-02-02 14:34:00

    学习了

  36. _龙猫
    *.*.*.*
    链接

    _龙猫 2009-02-02 16:30:00

    好。
    我也看到那篇文章,不过没有细究。

  37. 痘痘熊
    *.*.*.*
    链接

    痘痘熊 2009-02-13 11:58:00

    个人感觉C#正在迅速变得极为臃肿,这说不好是坏是好,但是复杂度和学习曲线在急剧增大。虽然都高阶程序员来说是不折不扣的好事,但是这可能导致c#开发人员水准的两极化,跟贫富差距似的。

  38. 老赵
    admin
    链接

    老赵 2009-02-13 12:17:00

    @痘痘熊
    我倒觉得它不必python,ruby等复杂,只是这种慢慢增加的语言特性让人心理上不是很爽吧。

  39. Rexzhou[未注册用户]
    *.*.*.*
    链接

    Rexzhou[未注册用户] 2009-02-13 12:29:00

    @不好意思
    public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
    foreach (var v in source)
    {
    action(v);
    }
    }

  40. 痘痘熊
    *.*.*.*
    链接

    痘痘熊 2009-02-13 13:53:00

    @Jeffrey Zhao
    至少已经比Java复杂很多了。这些语言特性其实好些年前就已经差不多了,但是一步一步的发布,频繁的发布,的确让人有点无所适从。尤其是维护老的项目,不能用新的features,觉得很烦人啊,很烦人。 BTW,不管如何,我还是强烈看好新特性的,什么扩展方法,lambda表达式等等,都很好用,呵呵。

  41. 老赵
    admin
    链接

    老赵 2009-02-13 14:13:00

    @痘痘熊
    Java这个不思进取的就不去学习它了。
    你说的还是心理作用,比如像Java一直不去进步,那么反而没有想法,但是C#一升级……就觉得很烦人,哈哈。

  42. viaivi[未注册用户]
    *.*.*.*
    链接

    viaivi[未注册用户] 2009-02-13 21:12:00

    哎,严重看不懂了,var matrix,俺还以为js呢 :)

  43. 文明的天空
    *.*.*.*
    链接

    文明的天空 2009-02-20 10:37:00

    class Program{
      static void Main(string[] args){
        Print("床前明月光疑似地上霜举头望明月低头思故乡", 5);
      }

      static void Print(string text, int offset) {
        for (int j = 0; j < offset; j++){
          for (int i = text.Length - offset + j; i >= 0; i -= offset){
            Console.Write(text[i] + "|");
          }
          Console.WriteLine();
        }
      }
    }
    赵哥,本人比较愚笨,只会这么写,你的那个我看不太懂,不过我会好好学习,挣取从中收获更多心得!

  44. 巴斯光年
    *.*.*.*
    链接

    巴斯光年 2009-04-12 11:56:00

    实际上,我认为诸如泛型、匿名方法、Linq、WWF、WPF、WCF等等这些语言上、架构上的改进确实提高了软件开发的效率。却在很大程度上磨灭了程序员最基本的内功——数据结构与算法。

    或许,做为一个程序员,有空的时候,应该想想如何使用低级的语言来实现问题算法,以不至于自己的大脑退化下去。

  45. 老赵
    admin
    链接

    老赵 2009-04-12 15:12:00

    @巴斯光年
    你的“低级语言”、“退化”结论我不同意,你的概念很奇怪……

  46. yiyanxiyin
    *.*.*.*
    链接

    yiyanxiyin 2009-04-19 23:14:00

    扩展方法咋没智能提示呢?比如string的GroupBy方法,点不出GroupBy方法,我用的vs2008, 如果输入完整的方法名,然后打“(”时能提示参数

  47. Tmac_
    *.*.*.*
    链接

    Tmac_ 2010-03-16 11:37:00

    static void Print(string text, int offset)
    {
        text
            .Select((c, i) => new { Char = c, Index = i })
            .GroupBy(c => c.Index % offset, c => c)
            .ForEach(g => Console.WriteLine(g.Reverse().Join("|")));
    }
    
    

    有个地方写错啦~
    应该是:
    GroupBy(c => c.Index % 5, c => c.Char)
    

  48. 发表回复

    登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

    昵称:(必填)

    邮箱:(必填,仅用于Gavatar

    主页:(可选)

    评论内容(大于5个字符):

    1. Your Name yyyy-MM-dd HH:mm:ss