C2 wiki имеет хорошую запись на конструкциях языка первого класса. В основном, это - материал, который Вы не должны фальсифицировать в языке.
Я копался в исходном коде distutils в течение дня, чтобы узнать о нем достаточно, чтобы сделать кучу настраиваемых команды. Это некрасиво, но работает.
If you liked chaowmans solution to the other question, this would be the logical extension to even/odd numbers:
int even = 17463.ToString().Where((c, i) => i%2==1).Sum(c => c - '0');
int odd = 17463.ToString().Where((c, i) => i%2==0).Sum(c => c - '0');
A loop might be simpler and more efficient though:
for (odd = even = 0; n != 0; n /= 10) {
tmp = odd;
odd = even*10 + n%10;
even = tmp;
}
And it's also not really longer or more complicated. Both versions determine the "oddness" from the left of the number.
"1234567".Where((ch, i) => i % 2 == 0).Sum(ch => ch - '0')
Ruben's version with modified Grouping logic:
bool isOdd = false;
var sums = 1234567
.ToString()
.Select(x => Char.GetNumericValue(x))
.GroupBy(x => isOdd = !isOdd)
.Select(x => new { IsOdd = x.Key, Sum = x.Sum() });
foreach (var x in sums)
Console.WriteLine("Sum of {0} is {1}", x.IsOdd ? "odd" : "even", x.Sum);
Вот мой однострочник, использующий LINQ, который (a) вычисляет четные и нечетные суммы в одной строке, (b) не делает 'не преобразовывать исходное число в промежуточную строку
, а (c) не имеет никаких побочных эффектов:
var totals = Enumerable.Range(0, 10)
.Select(x => (number / (int)Math.Pow(10, x)) % 10)
.Where(x => x > 0)
.Reverse()
.Select((x, i) => new { Even = x * (i % 2), Odd = x * ((i + 1) % 2) })
.Aggregate((a, x) => new { Even = a.Even + x.Even, Odd = a.Odd + x.Odd });
Console.WriteLine(number); // 1234567
Console.WriteLine(totals.Even); // 12
Console.WriteLine(totals.Odd); // 16
(Код выше считает нечетные / четные позиции из слева направо. Чтобы считать справа налево, просто удалите вызов Обратный
. Вычисление от L к R даст другие результаты, чем R-to-L, когда номер
имеет четное количество цифр.)
Если вы ищете версию с неизбежными тупыми уловками LINQ, вот одна:
var result = 1234567
.ToString()
.Select((c, index) => new { IndexIsOdd = index % 2 == 1, ValueOfDigit = Char.GetNumericValue(c) })
.GroupBy(d => d.IndexIsOdd)
.Select(g => new { OddColumns = g.Key, sum = g.Sum(item => item.ValueOfDigit) });
foreach( var r in result )
Console.WriteLine(r);
Я уверен, что кто-то скучающий может превратить ее в однострочную (и удалите ее преобразование в строку как способ генерации цифр).
РЕДАКТИРОВАТЬ: Использование кортежей, чтобы сделать ее короче (но более запутанной)
var result = 1234567
.ToString()
.Select((c, index) => Tuple.Create( index % 2 == 1, Char.GetNumericValue(c))
.GroupBy(d=>d.Item1)
.Select(g => new { OddColumns = g.Key, Sum = g.Sum(item => item.Item2) });
foreach( var r in result )
Console.WriteLine(r);
Я действительно не знаю C #, но вот однострочный текст, который может показаться Патрику Макдональду немного знакомым:
int oddSum = 0, evenSum = 0; bool odd = true; while (n != 0) { if (odd) oddSum += n % 10; else evenSum += n % 10; n /= 10; odd = !odd; }
int number = 1234567;
int oddSum = 0;
int evenSum = 0;
while(number!=0)
{
if (n%2 == 0) evenSum += number % 10;
else oddSum += number % 10;
number /= 10;
}
int evenSum = 1234567.ToString().ToCharArray().Where((c, i) => (i % 2 == 0)).Sum(c => c - '0');
int oddSum = 1234567.ToString().ToCharArray().Where((c, i) => (i % 2 == 1)).Sum(c => c - '0');
int n = 1234567; int[] c = new int[2]; int p = 0; n.ToString().Select(ch => (int)ch - '0').ToList().ForEach(d => { c[p] += d; p ^= 1; }); Console.WriteLine("even sum = {0}, odd sum = {1}", c[0], c[1]);
Более короткий:
int n = 1234567, p = 0; int[] c = new int[2]; while (n > 0) { c[p] += n % 10; n /= 10; p ^= 1; }; Console.WriteLine("even sum = {0}, odd sum = {1}", c[p ^ 1], c[p]);
This works if you're starting from the right. At least, it works in C++. I don't know C#, as I said. I kind of hope they removed some of this nonsense in C#.
It's not a one-liner, but it's one statement if you discount the declaration (which I think is fair):
int oddSum, evenSum;
for(bool odd = ((oddSum = evenSum = 0) == 0);
n != 0;
odd = (!odd || (n /= 10) == n + (oddSum += (odd ? n % 10 : 0) - evenSum + (evenSum += (!odd ? n % 10 : 0)))))
;
As extra credit, here's a one-line Python script that will turn all of your C# solutions into one-liners.
one_liner.py
open(__import__('sys').argv[2]','w').write(open(__import__('sys').argv[1],'r').read().replace('\n',''))
Usage:
python one_liner.py infile outfile
Это работает без LINQ.
var r = new int[]{0,0}; for (int i=0; i<7; i++) r[i%2]+="1234567"[i]-48;
System.Console.WriteLine("{0} {1}",r[0],r[1]);
It's not a one-liner, but the following works:
int oddSum = 0, evenSum = 0;
bool odd = true;
while (n != 0) {
if (odd)
oddSum += n % 10;
else
evenSum += n % 10;
n /= 10;
odd = !odd;
}
EDIT:
If you want it on one line:
int oddSum = 0, evenSum = 0; bool odd = true; while (n != 0) { if (odd) oddSum += n % 10; else evenSum += n % 10; n /= 10; odd = !odd; }