javascript — Вывести отсортированный список с помощью метода _.sortBy by underscore.js
Вопрос задан
Изменён 6 лет 9 месяцев назад
Просмотрен 391 раз
В проекте использованы backbone + underscore и jade + stylus.
В шаблоне jade имеется переменная, которая выводит не сортированный список
<% _.each(territory_list, function(territory) {%>
Для вывода списка используется метод _.each
.
Если я правильно понимаю, чтобы вывести отсортированный список, необходимо использовать метод _.sortBy
для выводимого списка territory_list
. Но не понимаю где этот метод применить. Представляю что запись должна быть примерно такая (не работает):
<% _.each_.sortBy(territory_list, function(territory) {%>
Как вывести отсортированный список с использованием метода от underscore?
UPD
Уточняю вопрос. В результате сортировки должен вывестись список по возрастающей. Например:
Территория 1 Территория 2 Территория 3 ... Территория 20
и т.д.
- javascript
- backbone.js
- underscore.js
Не знаю, откуда взялись ваши представления, но они абсолютно не верны (достаточно мельком просмотреть документацию Underscore.js чтобы в этом убедиться).
Более того, метод _.sortBy
нужен не для сортировки массивов строк, а для сортировки коллекций (массивов однотипных объектов). Для сортировки массива строк намного лучше подходит метод
Array.prototype.sort
. Но тут есть одна тонкость: этот метод использует лексикографический порядок строк при сортировке. То есть, вы получите:Foo 1 Foo 10 Foo 2
вместо
Foo 1 Foo 2 Foo 10
Чтобы получить правильный результат, вам нужно использовать натуральную сортировку вместо лексикографической. В общем виде, задача требует отдельного рассмотрения и может потребовать использования сторонних библиотек (например, javascript-natural-sort, но Google расскажет вам и о других, которые могут быть лучше/удобнее).
Если же все действительно так просто, как вы говорите в вопросе (сочетание слова «Территория» и целочисленного ее номера), то вам всего лишь надо передать правильную функцию-компаратор методу Array.prototype.sort
:
var territoryComparator = function(a, b) { var numRegExp = /(.*?)(\d+)$/; return parseInt(a.replace(numRegExp, '$2')) - parseInt(b.replace(numRegExp, '$2')) };
При этом, ваш шаблон должен иметь вид:
<% _.each(territory_list.sort(territoryComparator), function(territory) { %> <!-- А здесь вы можете отрисовывать ваши "территории" --> <% }) %>
Зарегистрируйтесь или войдите
Регистрация через Google Регистрация через Facebook Регистрация через почтуОтправить без регистрации
ПочтаНеобходима, но никому не показывается
Отправить без регистрации
ПочтаНеобходима, но никому не показывается

Underscore js
Underscore jsAdvertisement
1 of 33
Top clipped slideDownload to read offlineTechnology
Underscore.js
Advertisement
Advertisement
Advertisement
Underscore js
- Носова О.А. гр.4381
- Что такое Underscore Имя библиотеки Общие сведения Подключение Функциональность Underscore в действии Нужно ли это на самом деле Аналоги в JavaScript и др. языках
- Это библиотека JavaScript, реализующая дополнительную функциональность для работы с массивами, объектами и функциями, изначально отсутствующие в JavaScript, но имеющую аналоги в других языках. Библиотека Underscore сможет облегчить вам процесс разработки, не изменяя встроенных объектов.
- Дело все в том, что как в JQuery все
начинается со знака «$», так и тут все
начинается со знака «_», а Underscore с
английского как раз таки и переводится как
нижнее подчеркивание.
- На данный момент Underscore предоставляет более 80 функций. Среди них есть, те, которые решают более тривиальные задачи: map, select, invoke; но так же и более специфические: биндинг, javascript шаблоны и т.д. Сама библиотека функционально основана на нативных JavaScript методах, таких как forEach, map, reduce, filter, every, indexOf, что делает её значительно быстрой.
- в отличие от Prototype.js, Underscore не модифицирует прототипы встроенных объектов JavaScript. Данная особенность гарантирует бесконфликтность, что позволяет замечательно сочетать этот инструмент с, например, JQuery или Blackbone, или и тем и другим вместе. Библиотека умеет делегировать вызовы, если какая-то функциональность реализована разработчиками браузеров.
- Прежде чем мы начнем использовать эту
библиотеку, нам нужно ее подключить.
Найти библиотеку вы можете на сайте
разработчика underscorejs.org. Заметьте, что
там же вы можете найти документацию,
однако она будет на английском.
- Подключить Underscore не сложнее любой другой JavaScript-овой библиотеки. Теперь все доступные методы можем вызывать от объекта “_” (подчёркивание).
- Underscore обеспечивает немногим более 80 функций, которые охватывают целый ряд функциональных возможностей. По своей сути, они могут быть разделены на группы : Коллекции Массивы Объекты Функции Утилиты Цепные вызовы
- Коллекцией может быть либо массив или объект, ассоциированный массив в JavaScript, если он семантически правильный. Underscore предоставляет много методов которые работают на коллекциях.. Вот еще несколько полезных из них:
- Pluck Скажем, у вас есть хороший маленький массив, содержащий пары ключ-значение, и вы хотите извлечь только определенное свойство от каждого.
- map Cоздает массив из коллекции, где каждый элемент может быть тем или иным образом изменен с помощью функции
- All
All полезна, если вам нужно проверить
каждое значение в коллекции на
соответствию критерию.
- Underscore имеет кучу функций, которые работают исключительно на массивах, которые в высшей степени приветствуется, поскольку, по сравнению с другими языками, JavaScript предоставляет несколько методов, касающихся массивов
- Uniq Этот метод в основном разбирает массив и удаляет все повторяющиеся элементы, предоставляя вам только уникальные элементы.
- Range Чрезвычайно удобный метод, который позволяет создать ‘диапазон’ или список номеров. Давайте посмотрим на простой пример.
- Intersection Этот метод сравнивает два массива с каждым другим и возвращает список элементов, которые находятся во всех передаваемых массивов, т.е. пересечение в теории множеств. Давайте расширим предыдущий пример, чтобы увидеть, как это работает
- Intersection Легко, не так ли? Вы просто передать в список массивов для сравнения и Underscore делает все остальное
- В дополнение к довольно
ожидаемым проверкам, Underscore
предоставляет различные методы для
клонирования, расширения и другие
манипулировать объектами.
- Keys and Values Есть массивный объект, где вам нужно только ключи или только значения? Это легко с underscore.
- Defaults Этот метод весьма полезен, когда вам нужно создавать объекты с приемлемыми значениями по умолчанию, когда не могут быть использованы при его создании
- Underscore имеет функции, которые работают на функциях. Большинство функций, как правило, довольно сложно объяснить здесь, так что мы посмотрим на самый простой.
- Bind Связывает функцию с объектом. Это значит, что каждый раз когда она будет вызвана this будет указывать на данный объект. Это особенно полезно , когда вы работаете с обработчиком событий , где this переопределен.
- Underscore предоставляет массу полезных
функций.
Templating
Компилирует JavaScript-шаблоны в функции,
которые могут быть вызваны для рендеринга
этого шаблона. Полезно при рендеринге
объёмных и сложных частей HTML-разметки из
данных JSON. Полученные функции во время
обработки данных могут интерполировать
переменные, для чего используется следующий
синтаксис внутри шаблона: <%= … %>, а также
производить вычисления <% … %>.
- Вы можете использовать Underscore с применением как объектно-ориентированного подхода, так и процедурного, в зависимости от ваших привычек и предпочтений. Вызвав chain на объекте, с которым собираетесь работать, вы получите эффект, при котором каждый последующий метод в цепочке будет вызван на объекте, возвращённом предыдущим методом. Чтобы получить результат отработавших методов, нужно вызвать value.
- Давайте предположим, что у вас есть случайный набор тестов и вам нужен список тех, у кого 90+ балла. Вы бы обычно пишут что-то вроде этого:
- Вы можете подумать, зачем же использовать
эту библиотеку, когда есть JQuery? Не стоит
их путать. Все дело в том, что
в JQuery существует много функций, которые
позволяют не беспокоиться, к примеру, с
анимациями, а просто вызвать уже готовую.
То же самое с Ajax и т.д. Однако эта
библиотека не облегчает нам процесс
написания кода. Underscore же создана как
раз для этого. Давайте рассмотрим
некоторые ее возможности на примере.
- Давайте посмотрим на то, что мы можем достичь c Underscore в следующем: Код стал короче и более читабельным
- Все зависит от того, что вы пытаетесь сделать. Если использование JavaScript ограничивается игрой вокруг DOM, то ответ почти нет, так как JQuery делает большинство из того, что вы хотите сделать.
- С другой стороны, если вы имеете дело с кодом, не DOM, Underscore оказывается очень полезным. Underscore предоставляет вам хороший набор абстракций. Underscore возвращается в исходные реализации, если таковые имеются, чтобы убедиться, что производительность, как оптимальным, насколько это возможно.
- JavaScript – Array,Function,UnderScore,Lo-Dash Python — itertools, functools,funcy,toolz.fn.py Ruby – Enumerable, ActiveSupport PHP – functional-php, Inderscore.php Clojure – clojure.core Java – FunctionalJava, lambdaj C# — LINQ Objective-C – Underscore.m встроенные внешние
Advertisement
javascript — Как перевести шаблон Underscore в шаблон Handlebars?
Обычно Underscore и Handlebars не являются альтернативой друг другу. Underscore — это набор инструментов с общими функциональными утилитами, которые помогают писать более короткий и удобный для сопровождения код в функциональном стиле. С другой стороны, Handlebars — это библиотека, полностью посвященная рендерингу шаблонов, которая помогает вам писать более чистые и удобные в сопровождении шаблоны.
При использовании Underscore вы можете обнаружить, что его функции вызываются повсюду в вашем коде JavaScript, тогда как Handlebars вызывается только в тех местах, где вы будете отображать шаблон. По этой причине эти библиотеки обычно вообще не конфликтуют; вполне возможно написать приложение, которое зависит от обоих (на самом деле я делал это некоторое время в большинстве своих приложений). Просто свяжите обе библиотеки со своей страницей,
или импортировать как модули,
import _ from 'underscore'; импортировать * как руль из 'рулей';
или сделайте то же самое с более старым форматом модуля, таким как AMD или CommonJS.
Тем не менее, Underscore имеет функцию шаблона
, которая представляет собой очень минимальную реализацию шаблонов, которую можно использовать в качестве альтернативы библиотеке, такой как Handlebars. Похоже, это имело место в старой версии вашего приложения, и это вызывает конфликты, потому что минимальный язык шаблонов Underscore отличается от языка шаблонов Handlebars. Этапы компиляции и рендеринга также немного различаются между этими библиотеками.
Сравнение языков шаблонов
Оба языка шаблонов позволяют вставлять специальные теги в фрагмент текста, чтобы сделать части этого текста параметрическими, условными или повторяющимися. Однако теги, которые они поддерживают, отличаются.
Подчеркивание:
-
<%= выражение %>
вставит в текст строковое значение выражения JavaScript -
<%- выражение %>
сделает то же самое, но с HTML-экранированием. -
<% code %>
позволяет написать произвольный код JavaScript<% for (...) { %>
, а затем чуть дальше по шаблону есть соответствующий<% } %>
. Часть шаблона между этими двумя тегами кода представляет собой цикл, который будет повторяться по логикедля 9.0016 . Точно так же вы можете найти
<% if (...) { %>...<% } %>
, чтобы сделать часть шаблона...
условной. (Честно говоря, это довольно уродливо, но это помогает сделать реализацию минимальной. Модуль шаблона Underscore состоит только из одной страницы.) Внутри кода
<% code %>
иногда можно найтиprint(expression)
. Это сокращение предназначено для того, чтобы не выходить из тега кода, вставить тег интерполяции с, выражение
, а затем немедленно возобновите работу с новым кодовым тегом.Другими словами,
<% code1 print(expression) code2 %>
является сокращением для<% code1 %><%= expression %><% code2 %>
.
Handlebars:
{{имя}}
вставляет строковое значение свойства с экранированным HTML-кодом с ключомимя
в шаблон.{{{name}}}
делает то же самое, но без HTML-экранирования .{{#if condition}}...{{/if}}
вставит часть...
, только еслиусловие
выполнено.{{#each name}}...{{/each}}
будет повторяться...
для каждого элемента или свойства имениимя
становится контекстом из...
; то есть, если вы напишете{{otherName}}
в пределах...
, Handlebars попытается найтиotherName
как свойство объекта, идентифицированногоимя
.{{#name}}.
— это обозначение, которое Handlebars наследует от Mustache. Он ведет себя аналогично..{{/name}}
{{#each name}}
, когдаname
является массивом, и аналогично{{#if name}}
в противном случае (также изменение контекста наname
, если это объект). Идея, стоящая за этим (в Mustache), состоит в том, чтобы сделать шаблон еще более декларативным или «свободным от логики», как его называют авторы.Есть еще теги, которые я не буду сейчас рассматривать.
Преобразование шаблонов Underscore в Handlebars
Поскольку Underscore позволяет вставлять в шаблон произвольный код JavaScript, не всегда возможно преобразовать шаблон Underscore в эквивалентный шаблон Handlebars. Однако, к счастью, шаблоны на самом деле не нуждаются во всей выразительной силе JavaScript, поэтому шаблоны Underscore, скорее всего, будут написаны таким образом, что можно портировать на более строгий язык шаблонов («повезло случайно»).
Когда это возможно, в большинстве случаев будет достаточно следующей стратегии:
Замените все вхождения
print(_.escape(expression))
внутри любого тега<%...%>
на%><%- выражение %><%
.Замените любые другие вхождения
print(expression)
внутри<%...%>
на%><%= выражение %><%
.Заменить все вхождения
<%-выражение %>
(включая те, которые уже были до шага 1) на{{выражение}}
.Замените все вхождения
<%= выражение %>
(включая те, которые уже были до шага 2) на{{{выражение}}}
.Если вы найдете псевдонимы вида
var name = otherName.propertyName
где угодно ( кроме в скобках оператораfor (...)
), заменитеotherName.propertyName
наname
везде, где эта переменная находится в области видимости и отбросить переменную.Не сделать это с переменными цикла внутри
for (...)
; они заменяются на шаге 7.Если вы найдете шаблон вида
<% if (condition1) { %>...<% } else if (condition2) { %>...<% } else ... if (conditionN) { %> ...<% } else { %>...<% } %>
, начните с последнего, самого внутреннего блока и двигайтесь наружу оттуда следующим образом:- Заменить последний
<% } else { %>
на{{else}}
(Handlebars распознает это как специальное обозначение). - Замените последний промежуточный элемент
<% } else if (conditionN) { %>...<% } %>
на{{else}}{{#if conditionN }}...{{/if}}< % } %>
. Повторяйте этот шаг до тех пор, пока не останетсяelse if
. Обратите внимание, что последний<% } %>
остается на месте ; вы вставляете один дополнительный{{/if}}
перед ним для каждого промежуточногоelse if
. - Заменить самый внешний
<% if (condition1) { %>.
на..<% } %>
{{#if condition1}}...{{/if}}
. На этот раз последний<% } %>
исчезает.
- Заменить последний
Заменить циклы, снова начиная с самых внутренних выражений и продвигаясь оттуда наружу:
- Заменить функциональных цикла над объектами вида
<% _.each(objectName, function(valueName, keyName, collectionName) { %>...<% }) %>
нотацией{{#each objectName}}...{{/each}}
. Проверить вложенный{{}}
/{{{}}}
/{{#if}}
/{{#each}}
тегов в пределах...
для любых вхожденийkeyName
,collectionName
илиobjectName
и замените их на@key
,..
и..
соответственно (это не опечатка;collectionName
иobjectName
следует заменить на..
потому что они относятся к одному и тому же объекту). Обратите внимание, что функция передана_.
в версии Underscore может принимать меньше аргументов, в этом случаеeach
collectionName
и дажеkeyName
могут отсутствовать; замена работает одинаково независимо. - Заменить функциональных цикла над массивами вида
<% _.each(arrayName, function(valueName, indexName, collectionName) { %>...<% }) %>
нотацией{{#each arrayName }}...{{/каждый}}
. Проверить вложенный{{}}
/{{{}}}
/{{#if}}
/{{#each}}
тегов в пределах...
для любых вхожденийindexName
,collectionName
илиarrayName
и замените их на@index 9001 6,
..
и..
соответственно. Опять же, функция, переданная в_.each
в версии Underscore, может принимать меньше аргументов; замена работает одинаково независимо. Замена процедурных циклов над объектами вида
<% for (var keyName in objectName) { %>.
по нотации..<% } %>
{{#each objectName}}...{{/each}}
. Проверьте вложенные теги{{}}
/{{{}}}
/{{#if}}
/{{#each}}
в пределах...
на предмет появленияkeyName
,objectName[keyName]
илиobjectName
и замените их на@key
,это
и..
соответственно.Замена процедурных циклов по массивам вида
<% for (var indexName = 0; indexName < arrayName.length; ++indexName) { %>...<% } %>
по нотации{{#each arrayName}}... {{/каждый}}
. Проверьте вложенные теги{{}}
/{{{}}}
/{{#if}}
/{{#each}}
в пределах...
на предмет появленияindexName
,arrayName[indexName]
илиarrayName
и замените их на@index
,это
и.
соответственно..
- Заменить функциональных цикла над объектами вида
Исправить синтаксис выражения:
- Если на предыдущем шаге вы создали выражения вида
...propertyName
, где первые две точки..
изначально были именем (objectName
илиarrayName
, как описано в шаге 7), замените это../propertyName
. У вас могут быть более длинные пути этой формы, например../../propertyName
. - Подвыражения вида
name[index1][index2]
следует преобразовать вname.[index].[index2]
(обратите внимание на точки).
- Если на предыдущем шаге вы создали выражения вида
Проверьте, все ли
выражения
иусловия
, которые вы перевели, могут быть оценены Handlebars как есть. Как правило, Handlebars может напрямую оценивать (вложенные) имена свойств текущего контекста (например,keyName
илиkeyName.subProperty
) и некоторые специальные обозначения, которые он распознает, такие как@key
,@index
,@root
,это
и.
. Используйте помощники для оценки выражений, которые представляют собой нечто большее, чем просто имя некоторого объекта, и привязывайте имена по мере необходимости к.
@root
или..
:- Обратите внимание, что
this.propertyName
эквивалентно простоpropertyName
, потому чтоthis
относится к текущему контексту. - При передаче в шаблон такого объекта, как
{a: foo, b: {c: baz}}
, на свойства этого внешнего объекта всегда можно ссылаться с помощью@root.a
,@root.b.c
и так далее. Обратите внимание, что этому объекту могло быть присвоено собственное имя внутри исходного шаблона Underscore; в этом случае само это имя можно заменить на@root
. ..
предназначен для ссылки на родительский контекст внутри циклов, как мы видели в шагах 7-8. Иногда цикл в исходном шаблоне Underscore может напрямую ссылаться на свойство родительского контекста, закрывая его; в таких случаях вы можете помочь Handlebars найти нужное свойство, добавив к имени этого свойства префикс 9.0015 ../
- Обратите внимание, что
Возможно, у вас остались пустые
<% %>
тегов после предыдущих преобразований; их можно безопасно удалить.
Если после вышеперечисленных шагов у вас все еще есть нотация
<% code %>
в вашем шаблоне или выражения, которые Handlebars не может оценить, вам может потребоваться использовать другие средства языка Handlebars или создать специальные обходные пути. Если вам очень не повезло, то шаблон вообще нельзя будет перевести, но в большинстве случаев способ найдется.
Демонстрация: ваш шаблон
Повторение шаблона подчеркивания из вашего вопроса здесь:
<% } else { %> <% } %>>
<% если (успех) {%>
<% if (rates.length > 1) {%>
Для <%- address %> доступны <%- Rates.length %> тарифы на доставку, начиная с <%= Rates[0].price %>.
<% } иначе если (rates.length == 1) { %>
Для <%-адреса %> доступен один тариф доставки.
<% } иначе { %>
Мы не отправляем в этот пункт назначения.
<% } %>
<% } иначе { %>
<%- errorFeedback %>
<% } %>
<ул>
<% for (var i=0; i
<%- Rates[i].name %> по <%= Rates[i].price %>
<% } %>
Следуя приведенному выше алгоритму и используя выражение
ставок.[1]
вместо rate.length > 1
(поскольку Handlebars не может оценивать сравнения из коробки), мы успешно получаем следующий шаблон Handlebars:
{{#если успех}}
{{#если ставки.[1]}}
Для {{address}} доступны {{rates.length}} тарифы на доставку, начиная с {{{rates.[0].price}}}.
{{else}}{{#if ставки}}
Для {{address}} доступен один тариф доставки.
{{еще}}
Мы не отправляем в этот пункт назначения.
{{/если если}}
{{еще}}
{{отзыв об ошибке}}
{{/если}}
<ул>
{{#каждая ставка}}
{{name}} по цене {{{price}}}
{{/каждый}}
Возможно, вы найдете и другие шаблоны, которые необходимо перевести. Вы можете использовать тот же подход для других шаблонов.
Последнее примечание: шаблоны, встроенные в HTML
Ваша тема включает шаблон на странице со следующим обозначением.
<тип сценария = "текст/шаблон">
// шаблон
Важно понимать, что хотя это тег