Софтуерно Инженерство
Loading...
+ Нов въпрос
RoYaL avatar RoYaL SoftUni Team Trainer 6845 Точки

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 4502 Точки

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

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

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

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

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

0
RoYaL avatar RoYaL SoftUni Team Trainer 6845 Точки

По принцип е неправилно да работиш с обекти, които нямат 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 4502 Точки

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

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 SoftUni Team Trainer 6845 Точки

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

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 SoftUni Team Trainer 6845 Точки

Това не го знаех. Признавам си не бях отварял документацията за "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 SoftUni Team Trainer 6845 Точки

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

0