Loading...
RoYaL avatar RoYaL Trainer 6849 Точки

JS Basics подготовка за изпит 01.04.2015 - Задача 4

Днес присъствах на подготовката за изпит, която се проведе, и ми направи впечатление обсъждането около 4-та задача.

Задачата беше All that luggage от https://judge.softuni.bg/Contests/56/JavaScript-Basics-9-January-2015

Направи ми впечатление, че се кара малко на output driven development. Като ще трябва да изкараме един тип обект и директно се почва да се пълни такъв обект, пък после че трябва да се сортира - голяма работа :)

Накрая увиснахме с обект, който няма консистентни пропъртита. Единият има пропърти clothes, другият -  banana... :) Ходи ги сортирай.

Някой колега даде идея да се вкарат тези "багажи" в масив, а после да се изтрие квадратната скоба. Това би проработило, пак с известни хакове ще се сортират ключовете, но поне сортирането по килограми ще е по-лесно. За щастие нищо във входа не съдържа квадратни скоби и един стринг риплейс ще свърши работа. Аз не го намирам за много правилен вариант.

Това, което предлагам аз е да се пълни колекцията с туристи и багажи в удобен за програмиста начин, а не в удобен за изхода начин.

Една колекция, която съдържа обекти от следния тип

   ИмеНаТуриста: ...

   Багажи: {{нова колекция}}

         ИмеНаБагажа: ...

         Тегло: ...

         Чупливо: ...

         Тип: ...

         НачинНаТранспорт: ...

 

Това какво предимство ни дава? Можем да сортираме масив от обекти, по common property. Т.е. по ключ, който съществува във всеки един обект. А ако имаме ИмеНаБагажа и Тегло във всеки обект в колекцията с багажи, много лесно можем да сортираме тази колекция/масив.

И когато стане време да аутпутнем, просто ще превърнем нашия масив, в такъв обект какъвто го искат за изхода и ще го принтираме.

Прилагам едно решение, което скалъпих преди малко, може би не е най-оптиизираното, но имплементира тази идея. Със сигурност някои if-ове и цикли имат и по-хитър начин да се направят. Решението без коментарите е около 80 реда. Авторското е 50 реда, така че не казвам, че е по-кратко, но е reusable.

Използвам и един трик - нашия масив от багажи си има ключове "ИмеНаБагажа" и "Тегло", точно един от двата ключа, може да бъде критерий за сортиране. Така че директно взет от user input-а този критерий се слага във функцията за сортиране и се сортират. Няма нужда от switch/case. Има само един IF който проверява ако е "strict" да не прави нищо.

Позволих си да напиша целия този пост с идеята да дам хинт да се работи не по подхода - какъвто ще е изхода да тръгнем от него, а така да си нагласим нещата, че да са ни удобни за работа. Особено когато трябва да приложим сет от операции върху нещо голямо. Изходът винаги е трудната част в judge-а, но не трябва работата ни да се върти около него. Той се наглася все някак накрая :)

Ето го решението с коментари: http://pastebin.com/URpMje26

Успех на изпита.

12
JavaScript Fundamentals 02/04/2015 03:01:23
Filkolev avatar Filkolev 4482 Точки

Не смятам, че сортирането на ключове на обект е кой знае колко сложно стига да знаеш как да подходиш. Във всички случаи се пълни един обект с данни, след което преди принтирането се обработва изхода. Работата с масиви понякога може да е доста забиваща и да отнеме супер много време, докато с един обект ако знаеш какво правиш няма да имаш особени трудности. Това съм го научил по трудния начин.

Винаги е хубаво да се споделят различни подходи, защото в различни ситуации може един или друг да е по-подходящ. Но специално за изпита е доста важно хората да знаят как да боравят с обекти и ключовете им. Всичко останало е екстра и ако не знаеш как да си сортираш някакви пропъртита ще скъсаш доста нерви.

По-специално за тази задача, след като е напълнен първоначалният обект, за да се направи изхода просто се взимат ключовете за всеки човек (Object.keys(obj[owner]) примерно) и се сортират: keys.sort (function(a,b) {...}).

В твоя подход има и проблем с факта, че имаш доста нива: collection[k]["possessions"][p]["name"], което по време на изпит може супер много да те обърка, а колкото повече неща трябва да следиш, толкова по-вероятно е нещо да сбъркаш и накрая да загубиш време в дебъгване. Докато ако се работи директно с обект нещата са доста по-прости - обект с ключове хора, за всеки човек имаш обект с ключ вида багаж и инфо към него. В нито един момент не се налага да се влиза повече от две нива навътре в обекта и се намаляват местата, в които може да сбъркаш.

В заключение, индивидуално е. Това, което според теб е удобно, за мен е доста по-неудобно и error-prone.

0
RoYaL avatar RoYaL Trainer 6849 Точки

По принцип е неправилно да работиш с обекти, които нямат common keys. Уж два туриста, ама единия има пропърти ябълки, пък другия картофи? :) Това си плаче да бъде под ключа name, а не самото то да е име на ключ.

Ако се ползва фнукционалния форийч в js ще се избегне collection[k]["possessions"][p]["name"];

Де факто

collection.forEach(function(tourist) {

   // tourist е един обект вече

   tourist.possession.forEach(function(posssession) {

       // possession ти е един обект с багажи. Съответно posession.name е това collection[k]["possessions"][p]["name"];

   });

});

Аз напълно разбирам каква е идеята на задачата, той изходът нарочно е такъв, но ако примерно пиша един web service и трябва да изплюя json като изхода, който искат, и го пиша на произволен език (C#, Java...) никога няма да се забъркам с някакъв динамичен обект, и през целия апликейшън да го нося такъв. Според мен това е по error-prone.

Ти поне си учил ООП. Мислиш ли, че е error-prone да си дефинираш class Tourist и class Luggage? Двете имат следното

class Tourist

{

    public string Name;

    public List<Luggage> Luggages;

}

class Luggage

{

    public string Name;

    public double Weight;

    public string Type;

    public string TransferredWith

}

 

Структурата с която работиш е var collection = new List<Tourist>();

2
Filkolev avatar Filkolev 4482 Точки

От ООП гледна точка е по-правилно да, но след като се иска да имаме обект на изхода по-логичното е да се работи така, както се очаква. Шефа като ти каже, че иска в такъв формат данните ти може да пробваш да го убедиш, че е идиот, но в крайна сметка трябва да се съобразиш с изискването. И в случая, с цел да е по-правилно моделирането отдолу, нещата се усложняват - пак трябва да сортираш масиви и трябва да ги правиш на обекти. 

collection[k]["possessions"][p]["name"] го копирах от твоя код, не си успял да го избегнеш в проверките по-горе в кода. Аз лично имам доста проблеми при подобни ситуации, винаги губя много време да се ориентирам кое какво е.

result[tourist.name][possesion.luggagename] - пак не е много приятно, защото на всеки ключ достъпваш някакви пропъртита.

Това, което имам предвид е, че повечето хора, включително аз, трудно следят лесно толкова на брой променливи и вероятността да се допусне грешка (която се открива и по-трудно) е по-голяма.

0
Bi0GaMe avatar Bi0GaMe Trainer 389 Точки

Здравей Ванка,

 

Когато решавах изпита на една подготовка и аз имах същото наум. Не е хубаво да е промотираме output driven development. Точно заради това, на следващия изпит, задачата с обектите ще е input driven с common keys, за да има някакъв смисъл в цялата работа.

 

Поздрави,

Богомил

3
enevlogiev avatar enevlogiev 1168 Точки

Супер много исках да тествам нещо. То сработи ... почти. Идеята ми беше следната: Защо примерно да не сортирам инпута според това какво се иска от мен? Та подхождам по следния начин - минавам през целия инпут, правя всеки стринг на масив, пълня си един обект с ключове и толкова. След това сортирам самия инпут според критерия. Накрая си допълвам обекта. Принципно не бих подходил така, но човек трябва да тества всички варианти, за да знае кое се троши и кое не.
В случая нещо се строши - 88/100 в джъдж. Не издържах и погледнах тестовете. Оказа се, че на седми тест имам 'steak' - 5.8kg и 'rakiya'-5.8kg. По някаква причина, като сортирам по килограми, им сменя местата. Изобщо не мога да разбера защо. Ето го кода - http://pastebin.com/VYhZpL6N

 

Edit:

Aко приместя реда със 'steak' да е малко по-нагоре в инпута, не им сменя местата. Май имам лош късмет : D

0
02/04/2015 15:33:53
RoYaL avatar RoYaL Trainer 6849 Точки

Пробвал ли си сортиране с по-голямо а не с изваждане? Има шанс да не върне нула и да ги размени. През телефон съм и не мога да тествам.

0
enevlogiev avatar enevlogiev 1168 Точки

Пробвах всичко, дето ми дойде на акъла. Накрая си направих един мой си дървен бъбъл сорт и даде 100 точки.

1
vesheff avatar vesheff 13 Точки

Здравей.
Погледнах кода и наистина е доста по-лесно да сортираш обектите по common property. Обаче забелязах една малка неточност.

/**
* Determine if a tourist already has a luggage with that name
*/
if (collection[k]["possessions"][p]["name"] == posessionName) {
delete collection[k]["possessions"][p]
break;
}

Това име на пропърти е грешно. Не се влиза в този цикъл въобще. Трябва да е luggagename.
Аз не виждам смисъл от тази проверка при положение, че няма случай да се повтаря багажа. Дори да има случай на повтаряемост, ти просто записваш нов обект и триеш стария. Не се добавят нито килограми, нито нищо.

P.S. Имам и един въпрос :)


Като се промени на luggagename и се сложат два еднакви багажа на един човек.
-------------------------------------------------------------------------------------------------
Пример:

'Kiko......*...sticks..*false.....*false......*...false..*..1.6..*.ATV',
'Kiko......*...sticks..*false.....*false......*...false..*..1.8..*.ATV',
--------------------------------------------------------------------------

Тогава се затрива стария обект със 1.6кг и се слага нов 1.8кг. Обаче се получава ето това.
Може би аз не знам нещо, ама що се получава тая гадост :)
http://imgur.com/WiarPp3

 

0
02/04/2015 22:26:55
RoYaL avatar RoYaL Trainer 6849 Точки

Това не го знаех. Признавам си не бях отварял документацията за "delete". Сега я отворих, документирано е:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

"When you delete an array element, the array length is not affected. This holds even if you delete the last element of the array."

Май в такива случая трябва да му намериш индекса и splice(index, 1);

 

0
vesheff avatar vesheff 13 Точки

Дамммм красота. Квото и да кажа ще е малко :D Моя любима JS 

0
RoYaL avatar RoYaL Trainer 6849 Точки

https://pbs.twimg.com/media/CBHjP0bUQAE1zo0.jpg:large

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.