代码之家  ›  专栏  ›  技术社区  ›  Falco Alexander

LINQ表达式在文字上的行为不同?

  •  0
  • Falco Alexander  · 技术社区  · 6 年前

    在一个不同的SO问题中,要求获得一个有符号整数,逆位: 123变为321,-123变为-321

    int reverse (int i) {
        int sign = i/Math.Abs(i);
        var abs = string.Concat(Math.Abs(i).ToString().Reverse());
        return int.Parse(abs)*sign;
    }
    

    还建议使用更紧凑的LINQ表达式: .ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');

    但我不理解后者的结果:

    int j = -123;
    
    int a =  j.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
    int b = -(123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0'));
    int c = -123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
    int d = -(123).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
    Console.WriteLine($"{a} , {b} , {c} , {d}");
    

    3207 , -321 , -321 , -321
    

    为什么它只适用于文本int?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Fabjan    6 年前

    原因是除了 a 这个 int 转化为 string .ToString 呼叫

    在此表达式中:

    -123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0')
    

    这个 .ToString() int

    -1 * 123.ToString().Reverse().Aggregate(...)
    

    即使是这句话:

    int d = -(123).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
    

    将被转换为以下内容:

    int d = -1 * (123).someExpr
    

    首先编译器删除多余的括号,然后执行表达式,最后将结果的符号改为负号

    附笔。

    正如@PetSerAI正确指出的,您可以修改LINQ表达式,使其工作如下:

    int d = Math.Sign(j) * Math.Abs(j).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0')
    
        2
  •  2
  •   Michael Puckett II    6 年前

    a 你从 -123 但是对于你刚开始的其他人 123 并得出结果 -

    你需要像这样把123封起来 (-123)

    using System;
    using System.Linq;
    
    public class Program
    {
    
        public static void Main()
        {
            int j = -123;
    
            int a = j.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
            int b = -(123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0'));
            int c = -123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
            int d = -(123).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
    
            //Make -123 like line below.
            int e = (-123).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
    
            Console.WriteLine($"{a} , {b} , {c} , {d}, {e}");
            Console.ReadKey();
        }
    }
    //OUTPUTS
    //3207 , -321 , -321 , -321, 3207
    

    编辑

    我在上面回答了为什么你不能用这种方法得到正确的结果,但我没有回答如何才能实现。现在我同意你的看法;“这个没有很好的LINQ表达式”。然而我能够将它转换成一行可读性良好的代码,从而成为一个外观美观的扩展方法。

    我确实看了问题下面的评论,并借用了Falco Alexander的评论 Math.Sign if x < 0 return result * -1 索塔交易。

    我还注意到了电流的一个问题 Aggregate 正在使用的函数,即它不支持小数。目前只是 int double 也要添加小数点,我聚合了一个 string ; 但是我认为聚合一个字符串是一件坏事,因为我们只想执行尽可能少的字符串计算,只是做了一个简单的计算 new string

    using System;
    using System.Linq;
    
    public class Program
    {
        public static void Main()
        {
            int j = -123;        
            int k = 123;        
            double l = -123.456;
            double m = 123.456;
    
            Console.WriteLine(j.Reverse());
            Console.WriteLine(k.Reverse());
            Console.WriteLine(l.Reverse());
            Console.WriteLine(m.Reverse());
            Console.ReadKey();
        }
    }
    
    public static class Extensions
    {
        public static int Reverse(this int value)
        {
            return Math.Sign(value) * int.Parse(new string(Math.Abs(value).ToString().Reverse().ToArray()));
        }
    
        public static double Reverse(this double value)
        {
            return Math.Sign(value) * double.Parse(new string(Math.Abs(value).ToString().Reverse().ToArray()));
        }
    }
    //OUTPUTS
    //-321
    //321
    //-654.321
    //654.321