Поскольку контейнеры хранят объекты, а ссылки не являются объектами. Если вы находитесь на c ++ 11, вы можете использовать std :: reference_wrapper для переноса объектов в назначаемые объекты.
http://en.cppreference.com/w/cpp/utility/functional/ reference_wrapper
std :: reference_wrapper - это шаблон класса, который обертывает ссылку в подлежащем копированию присваиваемом объекте. Он часто используется как механизм для хранения ссылок внутри стандартных контейнеров (например, std :: vector), которые обычно не могут содержать ссылки.
Вот то, как мы делаем это. Обратите внимание, что существует, вероятно, больше граничных условий, чем Вы понимаете на первый взгляд.
Это - вторая версия, развернутая для 5x больше производительности (и да, я сравнил его). Я полагал, что оптимизирую его, потому что эта функция может быть вызвана сотни времен на страницу.
/// <summary>
/// Produces optional, URL-friendly version of a title, "like-this-one".
/// hand-tuned for speed, reflects performance refactoring contributed
/// by John Gietzen (user otac0n)
/// </summary>
public static string URLFriendly(string title)
{
if (title == null) return "";
const int maxlen = 80;
int len = title.Length;
bool prevdash = false;
var sb = new StringBuilder(len);
char c;
for (int i = 0; i < len; i++)
{
c = title[i];
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
{
sb.Append(c);
prevdash = false;
}
else if (c >= 'A' && c <= 'Z')
{
// tricky way to convert to lowercase
sb.Append((char)(c | 32));
prevdash = false;
}
else if (c == ' ' || c == ',' || c == '.' || c == '/' ||
c == '\\' || c == '-' || c == '_' || c == '=')
{
if (!prevdash && sb.Length > 0)
{
sb.Append('-');
prevdash = true;
}
}
else if ((int)c >= 128)
{
int prevlen = sb.Length;
sb.Append(RemapInternationalCharToAscii(c));
if (prevlen != sb.Length) prevdash = false;
}
if (i == maxlen) break;
}
if (prevdash)
return sb.ToString().Substring(0, sb.Length - 1);
else
return sb.ToString();
}
Для наблюдения предыдущей версии кода это заменило (но функционально эквивалентно, и 5x быстрее), история пересмотра представления этого сообщения (нажмите на ссылку даты).
кроме того, RemapInternationalCharToAscii
исходный код метода может быть найден здесь .
Нет, нет, нет. Вы - все так очень неправильно. За исключением материала диакритических-знаков-fu, Вы добираетесь там, но что относительно азиатских символов (позор разработчикам Ruby для того, чтобы не рассматривать их nihonjin братья).
Firefox и Safari и отображают символы неASCII в URL, и откровенно они выглядят великими. Хорошо поддерживать ссылки как' http://somewhere.com/news/read/гЃЉе‰ЌгЃџгЃЎгЃЇг‚ ўгѓ ›гЃг‚ ѓгЃЄгЃ „гЃ‹ гЃ „'.
, Таким образом, вот некоторый код PHP, это сделает это, но я просто записал это и не имею напряжения, протестировал его.
<?php
function slug($str)
{
$args = func_get_args();
array_filter($args); //remove blanks
$slug = mb_strtolower(implode('-', $args));
$real_slug = '';
$hyphen = '';
foreach(SU::mb_str_split($slug) as $c)
{
if (strlen($c) > 1 && mb_strlen($c)===1)
{
$real_slug .= $hyphen . $c;
$hyphen = '';
}
else
{
switch($c)
{
case '&':
$hyphen = $real_slug ? '-and-' : '';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
$real_slug .= $hyphen . $c;
$hyphen = '';
break;
default:
$hyphen = $hyphen ? $hyphen : ($real_slug ? '-' : '');
}
}
}
return $real_slug;
}
Пример:
$str = "~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 コリン ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 トーマス ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 アーノルド ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04";
echo slug($str);
Выводы: г‚ €гѓјгѓћг ігѓЄгѓі-гѓ‚ №-and-г‚ ўгѓјгѓЋгѓ «гѓ ‰
'-and-' то, потому что & будьте изменены на '-and-'.
Код Brian, в Ruby:
title.downcase.strip.gsub(/\ /, '-').gsub(/[^\w\-]/, '')
downcase
повороты строка к нижнему регистру, strip
удаляет ведущий и запаздывающий пробел, первое gsub
вызов пробелы globally substitutes с тире, и второе удаляет все, что не является буквой или тире.
Существует маленький плагин Ruby on Rails, названный PermalinkFu, который делает это. метод Escape делает преобразование в строку, которая подходит для URL. Взгляните на код; тот метод довольно прост.
Для удаления не - символы ASCII это использует iconv lib для перевода в 'ASCII//, игнорируют//трансосвещенный' от 'utf-8'. Пробелы тогда превращены в тире, все - downcased, и т.д.
Реализация T-SQL, адаптированная от dbo. UrlEncode:
CREATE FUNCTION dbo.Slug(@string varchar(1024))
RETURNS varchar(3072)
AS
BEGIN
DECLARE @count int, @c char(1), @i int, @slug varchar(3072)
SET @string = replace(lower(ltrim(rtrim(@string))),' ','-')
SET @count = Len(@string)
SET @i = 1
SET @slug = ''
WHILE (@i <= @count)
BEGIN
SET @c = substring(@string, @i, 1)
IF @c LIKE '[a-z0-9--]'
SET @slug = @slug + @c
SET @i = @i +1
END
RETURN @slug
END
Я не делаю многого о Ruby или направляющих, но в Perl, это - то, что я сделал бы:
my $title = "How do you change a title to be part of the url like Stackoverflow?";
my $url = lc $title; # Change to lower case and copy to URL.
$url =~ s/^\s+//g; # Remove leading spaces.
$url =~ s/\s+$//g; # Remove trailing spaces.
$url =~ s/\s+/\-/g; # Change one or more spaces to single hyphen.
$url =~ s/[^\w\-]//g; # Remove any non-word characters.
print "$title\n$url\n";
я просто сделал быстрый тест, и это, кажется, работает. Надо надеяться, это относительно легко перевести в Ruby.
Я не знаком с Ruby on Rails, но следующее (не тестируется) код PHP. Можно, вероятно, перевести это очень быстро в Ruby on Rails при нахождении его полезным.
$sURL = "This is a title to convert to URL-format. It has 1 number in it!";
// To lower-case
$sURL = strtolower($sURL);
// Replace all non-word characters with spaces
$sURL = preg_replace("/\W+/", " ", $sURL);
// Remove trailing spaces (so we won't end with a separator)
$sURL = trim($sURL);
// Replace spaces with separators (hyphens)
$sURL = str_replace(" ", "-", $sURL);
echo $sURL;
// outputs: this-is-a-title-to-convert-to-url-format-it-has-1-number-in-it
я надеюсь, что это помогает.
При использовании края направляющих можно полагаться , Inflector.parametrize - вот является примером из документации:
class Person
def to_param
"#{id}-#{name.parameterize}"
end
end
@person = Person.find(1)
# => #<Person id: 1, name: "Donald E. Knuth">
<%= link_to(@person.name, person_path(@person)) %>
# => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
Также, если необходимо обработать более экзотические символы, такие как диакритические знаки (Г©phГ©mГЁre) в предыдущей версии направляющих, можно использовать смесь PermalinkFu и DiacriticsFu:
DiacriticsFu::escape("éphémère")
=> "ephemere"
DiacriticsFu::escape("räksmörgås")
=> "raksmorgas"
В придачу вот функция PHP в WordPress, которая делает это... Я думал бы, что WordPress является одной из более популярных платформ, которая использует необычные ссылки.
function sanitize_title_with_dashes($title) { $title = strip_tags($title); // Preserve escaped octets. $title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title); // Remove percent signs that are not part of an octet. $title = str_replace('%', '', $title); // Restore octets. $title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title); $title = remove_accents($title); if (seems_utf8($title)) { if (function_exists('mb_strtolower')) { $title = mb_strtolower($title, 'UTF-8'); } $title = utf8_uri_encode($title, 200); } $title = strtolower($title); $title = preg_replace('/&.+?;/', '', $title); // kill entities $title = preg_replace('/[^%a-z0-9 _-]/', '', $title); $title = preg_replace('/\s+/', '-', $title); $title = preg_replace('|-+|', '-', $title); $title = trim($title, '-'); return $title; }
Эта функция, а также некоторые функции поддержки может быть найдена в wp-includes/formatting.php.
Можно также использовать этот функция JavaScript для поколения в хорошей форме краткого заголовка (этот базируется на от Django):
function makeSlug(urlString, filter) {
// Changes, e.g., "Petty theft" to "petty_theft".
// Remove all these words from the string before URLifying
if(filter) {
removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
"is", "in", "into", "like", "of", "off", "on", "onto", "per",
"since", "than", "the", "this", "that", "to", "up", "via", "het", "de", "een", "en",
"with"];
}
else {
removelist = [];
}
s = urlString;
r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
s = s.replace(r, '');
s = s.replace(/[^-\w\s]/g, ''); // Remove unneeded characters
s = s.replace(/^\s+|\s+$/g, ''); // Trim leading/trailing spaces
s = s.replace(/[-\s]+/g, '-'); // Convert spaces to hyphens
s = s.toLowerCase(); // Convert to lowercase
return s; // Trim to first num_chars characters
}
Вы захотите установить пользовательский маршрут для указания URL к контроллеру, который обработает его. Так как Вы используете Ruby on Rails, вот введение в использовании их механизма маршрутизации.
В Ruby, Вам будет нужно регулярное выражение как Вы, уже знают, и вот регулярное выражение для использования:
def permalink_for(str)
str.gsub(/[^\w\/]|[!\(\)\.]+/, ' ').strip.downcase.gsub(/\ +/, '-')
end
Предполагая, что Ваш образцовый класс имеет атрибут заголовка, можно просто переопределить to_param метод в рамках модели, как это:
def to_param
title.downcase.gsub(/ /, '-')
end
Этот эпизод Railscast имеет все подробности. Можно также удостовериться, что заголовок только содержит допустимые символы с помощью этого:
validates_format_of :title, :with => /^[a-z0-9-]+$/,
:message => 'can only contain letters, numbers and hyphens'