Страницы

Поиск по вопросам

понедельник, 4 февраля 2019 г.

LINQ сортировка по динамическим параметрам

Прошу помощи в оптимизации LINQ сортировки. Код написанный ниже, был написан по принципу "ну ведь так же работает?". Но он не красив, не гибок, и хотелось бы понять, как можно и можно ли через линкью, в качестве параметра для сортировки, указывать List.
var newItemsReportInfo = new List(); switch (itemsReportInfo[0].SortingTH.Count) { case 0: newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList(); break; case 1: newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.SortingTH[0], new TechDataComparer()) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList(); break; case 2: newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.SortingTH[0], new TechDataComparer()) .ThenBy(c => c.SortingTH[1], new TechDataComparer()) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList(); break; case 3: newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.SortingTH[0], new TechDataComparer()) .ThenBy(c => c.SortingTH[1], new TechDataComparer()) .ThenBy(c => c.SortingTH[2], new TechDataComparer()) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList(); break; case 4: newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.SortingTH[0], new TechDataComparer()) .ThenBy(c => c.SortingTH[1], new TechDataComparer()) .ThenBy(c => c.SortingTH[2], new TechDataComparer()) .ThenBy(c => c.SortingTH[3], new TechDataComparer()) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList(); break; case 5: newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.SortingTH[0], new TechDataComparer()) .ThenBy(c => c.SortingTH[1], new TechDataComparer()) .ThenBy(c => c.SortingTH[2], new TechDataComparer()) .ThenBy(c => c.SortingTH[3], new TechDataComparer()) .ThenBy(c => c.SortingTH[4], new TechDataComparer()) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList(); break; case 6: newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.SortingTH[0], new TechDataComparer()) .ThenBy(c => c.SortingTH[1], new TechDataComparer()) .ThenBy(c => c.SortingTH[2], new TechDataComparer()) .ThenBy(c => c.SortingTH[3], new TechDataComparer()) .ThenBy(c => c.SortingTH[4], new TechDataComparer()) .ThenBy(c => c.SortingTH[5], new TechDataComparer()) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList(); break; default: newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.SortingTH[0], new TechDataComparer()) .ThenBy(c => c.SortingTH[1], new TechDataComparer()) .ThenBy(c => c.SortingTH[2], new TechDataComparer()) .ThenBy(c => c.SortingTH[3], new TechDataComparer()) .ThenBy(c => c.SortingTH[4], new TechDataComparer()) .ThenBy(c => c.SortingTH[5], new TechDataComparer()) .ThenBy(c => c.SortingTH[6], new TechDataComparer()) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList(); break; }
Как видно из кода, мы всегда смотрим на размер itemsReportInfo[0].SortingTH и далее уже применяем один из методов сортировки. Хотелось бы заменить этот код, на код вида.
newItemsReportInfo = itemsReportInfo.OrderBy(x => x.FlyerPos) .ThenBy(x => x.SortingTH, new TechDataComparer()) .ThenBy(x => x.Description) .ThenBy(x => x.Flieztext) .ToList();


Ответ

Попробуйте что-то в таком стиле:
var newItemsReportInfo = new List();
var query = itemsReportInfo.OrderBy(x => x.FlyerPos);
for (int i = 0; i < itemsReportInfo[0].SortingTH.Count; i++) { query = query.ThenBy(x => x.SortingTH[i], new TechDataComparer()); }
query = query.ThenBy(x => x.Description); query = query.ThenBy(x => x.Flieztext); newItemsReportInfo = query.ToList();

Считается ли нормальным такой стиль написания кода?

public class MainTest { PracticeWork1 grades;
MainTest() { grades = new PracticeWork1(); init(); }
public static void main(String[] args) { new MainTest(); }
public void init() { testOut(); grades.adder(); testOut(); grades.adder(98); testOut(); } }
пример 2
public class MyWin extends JFrame {
private static final long serialVersionUID = 1L;
public MyWin() { Container c = getContentPane(); c.setLayout(new BorderLayout());
Panel child= new Panel(); c.add(child); setTitle("Example window");
setPreferredSize(new Dimension(640, 480));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true); // отображаем окно }
public static void main(String args[]) { new MyWin(); } }
Правильно ли в методе main создавать обьект того класса в котором этот мейн находиться , а не прописывать большинство логики в нём ?


Ответ

Если я правильно понял ваш вопрос, он о том, можно ли помещать логику класса в конструктор.
Технически это возможно и будет работать, но с точки зрения смысла кода это не очень хорошо. Конструктор должен конструировать класс, а действие должно запускаться каким-либо методом
Если ваш проект маленький, вы можете нарушить это правило (как и многие другие), но для более-менее серьёзного проекта я бы посоветовал оставлять в конструкторе лишь инициализацию.

Как вывести в консоль следующий месяц?

import datetime today = datetime.date.today() month = today.strftime("%b")# Показать текущий месяц print(month)
Данный код выводит текущий месяц, в данном случае "Jan" Как вывести следующий месяц в таком же формате?


Ответ

import calendar import datetime
today = datetime.date.today() calendar.month_abbr[today.month%12 + 1]

TypeError при изменении списка оператором += внутри кортежа

Известно, что оператор += для списков примерно эквивалентен методу extend в том смысле, что при его использовании не создаётся копия списка, а расширяется текущий.
В связи с этим возникает вопрос: почему следующая конструкция бросает исключение TypeError
t = ([1], ) # кортеж из одного элемента, являющегося списком try: t[0] += [2] except TypeError as e: print(e) # 'tuple' object does not support item assignment print(t) # ([1, 2],) -- и сам список изменился!
Ведь мы не изменяем ссылки, сохранённые в кортеже и следующий код работает без проблем:
t = ([1], ) t[0].extend([2]) print(t) # ([1, 2],)
Почему такое поведение?


Ответ

Дело в том, что операция += всё же содержит в себе присваивание, хоть и выполняет изменение "на месте". Оператор += реализуется через метод __iadd__, и код
t[0] += [2]
эквивалентен следующей записи
res = t[0].__iadd__([1]) t[0] = res # TypeError: 'tuple' object does not support item assignment
Хоть ссылка на самом деле и не меняется:
print(res is t[0]) # True
но присваивание есть, и это мешает выполниться подобному оператору без ошибок.
Способ с использованием метода, очевидно, такой проблемы иметь не может.

Можно удостовериться, что присваивание действительно есть. Для этого рассмотрим более простой случай:
a = [1] a += [2]
Посмотрим, какой код генерируется в Python 3 для выполнения второй строки (операции могут отличаться, но суть будет примерно та же):
import dis dis.dis('a += [2]') Расшифровка действия со стеком 1 0 LOAD_NAME 0 (a) push [1] (переменная "a") 3 LOAD_CONST 0 (2) push 2 6 BUILD_LIST 1 pop (2), push [2] 9 INPLACE_ADD pop ([2]), pop ([1]), push [1, 2] 10 STORE_NAME 0 (a) pop ([1, 2] -> a) ...
Именно попытка выполнить операцию STORE_NAME (более точно, STORE_SUBSCR, для кортежа) вызывает ошибку в случае, описанном в вопросе. Важно понимать, что операция INPLACE_ADD выполняет добавление элементов "на месте", т.е. на стеке в итоге окажется тот же объект.

Google Chrome. Жёлтый эффект.

Когда Google Chrome запоминает поля ввода, такие как логин и пароль, то фон поля ввода становится жёлтого цвета. Можно каким-либо способом устранить данный эффект?


Ответ

попробуйте
input:-webkit-autofill { -webkit-box-shadow: 0 0 0px 1000px white inset; }

C#: Создать и вызвать анонимную функцию внутри выражения

Есть ли способ в C# создать и вызвать анонимную функцию внутри выражения? Без предварительного объявления переменной-делегата. Что-то вроде этого:
int i32 = () => { int x = 5; int y = 6; return( x+y ); }();
или
int i32 = (() => { int x = 5; int y = 6; return( x+y ); })();
или
int32 = this.Invoke( () => { int x = 5; int y = 6; return( x+y ); } );
Работающий вариант #1 от @PashaPash и @Pavel Mayorov:
int i32 = ((Func)(() => { int x = 5; int y = 6; return( x+y ); }))();
Работающий вариант #2 от @Stack:
int i32 = new Func(() => { int x = 5; int y = 6; return (x+y); })();
Работающий вариант #3 от @Stack: (чемпион по краткости, по красоте - для ценителей)
int i32; new Action(() => { int x = 5; int y = 6; i32 = x + y; })();
Ответ на вопрос @Stack "Зачем это надо?:" Для красоты и компактности, требуется редко, вот пример:
int i1 = 5 + 6; int i2 = 7 + 8; int i3 = ((Func)(() => { int x = 45; int y = 6; return( x*2 + y*3 ); }))(); int i4 = 9 + 10; int i5 = 11 + 20; int i6 = new Func(() => { int x; if( CheckState( out x ) ) return( x ); else return( -1 ) })(); int i7 = new Func(() => { int x = 0; while( CheckSomthing( x )) x++; return( x ); })();
Вот, ещё один пример из реальной жизни:
Style s = new Style(); s.TargetType = typeof(System.Windows.Controls.ComboBox); s.Setters.Add(new Setter(System.Windows.Controls.ComboBox.FontSizeProperty, 11.0)); s.Setters.Add(new Setter(System.Windows.Controls.ComboBox.BackgroundProperty, ((Func)(() => { Brush b = new SolidColorBrush( Color.FromArgb( 255, 200, 200, 200 )); b.Freeze(); return b; }))() )); s.Setters.Add(new Setter(System.Windows.Controls.ComboBox.ForegroundProperty, Brushes.Black)); s.Setters.Add(new Setter(System.Windows.Controls.ComboBox.FontFamilyProperty, new FontFamily("Arial"))); s.Setters.Add(new Setter(System.Windows.Controls.ComboBox.FontWeightProperty, FontWeights.Bold));


Ответ

Это можно сделать вот так:
var q = ((Func)(() => { int x = 5; int y = 6; return( x+y ); }))()
Это - единственный способ.

Как можно редактировать имена txt файлов в архиве zip

Есть zip архив. В нем 1000 txt файлов. Мне надо всех их редактировать(если можно то без распаковки, просто имя поменять им)
Пример: name-lord
первая замена ame-lord (Remove(0,1)) вторая замена ame-word (Replace("-l","-w")) и последняя same-word (Добавить букву в начале имени файла)
Как сделать через c# ?
В какой архив закинул там и будет выполнятся алгоритм....


Ответ

Используя библиотеку DotNetZip, можно сделать так:
Пример взять отсюда
using (ZipFile zip2 = ZipFile.Read(ExistingZipFile)) { foreach (ZipEntry e in zip2) { if (e.FileName.EndsWith(".txt")) { var newname = e.FileName + "rename"; e.FileName = newname; } } zip2.Save(); }
Переименовываем все файлы с расширением .txt, добавляю к существующему названию каждого файла суффикс rename
Для вашего случая замените соответствующую строку на следующий код:
var newname = e.FileName.Substring(1, s.Length - 1); // первая замена newname = newname.Replace("-l", "-w" ); // вторая замена newname = "s" + newname; // третья замена