Мне не удалось найти что-либо в стандартной библиотеке, поэтому я написал свой собственный :
. Эта версия использует нестабильный API-интерфейс, поскольку он более гибкий, но ссылка выше, имеет резерв, который я жестко запрограммировал для своей конкретной стабильной usecase.
#![feature(pattern)]
use std::str::pattern::{Pattern, Searcher};
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SplitType<'a> {
Match(&'a str),
Delimiter(&'a str),
}
pub struct SplitKeepingDelimiter<'p, P>
where
P: Pattern<'p>,
{
searcher: P::Searcher,
start: usize,
saved: Option,
}
impl<'p, P> Iterator for SplitKeepingDelimiter<'p, P>
where
P: Pattern<'p>,
{
type Item = SplitType<'p>;
fn next(&mut self) -> Option {
if self.start == self.searcher.haystack().len() {
return None;
}
if let Some(end_of_match) = self.saved.take() {
let s = &self.searcher.haystack()[self.start..end_of_match];
self.start = end_of_match;
return Some(SplitType::Delimiter(s));
}
match self.searcher.next_match() {
Some((start, end)) => {
if self.start == start {
let s = &self.searcher.haystack()[start..end];
self.start = end;
Some(SplitType::Delimiter(s))
} else {
let s = &self.searcher.haystack()[self.start..start];
self.start = start;
self.saved = Some(end);
Some(SplitType::Match(s))
}
}
None => {
let s = &self.searcher.haystack()[self.start..];
self.start = self.searcher.haystack().len();
Some(SplitType::Match(s))
}
}
}
}
pub trait SplitKeepingDelimiterExt: ::std::ops::Index<::std::ops::RangeFull, Output = str> {
fn split_keeping_delimiter(&self, pattern: P) -> SplitKeepingDelimiter
where
P: for<'a> Pattern<'a>,
{
SplitKeepingDelimiter {
searcher: pattern.into_searcher(&self[..]),
start: 0,
saved: None,
}
}
}
impl SplitKeepingDelimiterExt for str {}
#[cfg(test)]
mod test {
use super::SplitKeepingDelimiterExt;
#[test]
fn split_with_delimiter() {
use super::SplitType::*;
let delims = &[',', ';'][..];
let items: Vec<_> = "alpha,beta;gamma".split_keeping_delimiter(delims).collect();
assert_eq!(
&items,
&[
Match("alpha"),
Delimiter(","),
Match("beta"),
Delimiter(";"),
Match("gamma")
]
);
}
#[test]
fn split_with_delimiter_allows_consecutive_delimiters() {
use super::SplitType::*;
let delims = &[',', ';'][..];
let items: Vec<_> = ",;".split_keeping_delimiter(delims).collect();
assert_eq!(&items, &[Delimiter(","), Delimiter(";")]);
}
}
Вы заметите, что мне нужно было отслеживать, было ли что-то одним из разделителей или нет, но это должно быть легко адаптируйте, если вам это не нужно.
Можно сделать это этот путь:
list.sort(key=lambda item:item['date'], reverse=True)
from operator import itemgetter
your_list.sort(key=itemgetter('date'), reverse=True)
не используют list
, dict
как имена переменной, они - встроенные имена в Python. Это делает Ваш код трудно для чтения.
Вы, возможно, должны были бы заменить словарь tuple
или collections.namedtuple
или пользовательский подобный структуре класс в зависимости от контекста
from collections import namedtuple
from operator import itemgetter
Row = namedtuple('Row', 'title date')
rows = [Row(row.title, row.created_on) for row in data]
rows.sort(key=itemgetter(1), reverse=True)
Пример:
>>> lst = [Row('a', 1), Row('b', 2)]
>>> lst.sort(key=itemgetter(1), reverse=True)
>>> lst
[Row(title='b', date=2), Row(title='a', date=1)]
Или
>>> from operator import attrgetter
>>> lst = [Row('a', 1), Row('b', 2)]
>>> lst.sort(key=attrgetter('date'), reverse=True)
>>> lst
[Row(title='b', date=2), Row(title='a', date=1)]
Вот то, как namedtuple
взгляды внутри:
>>> Row = namedtuple('Row', 'title date', verbose=True)
class Row(tuple):
'Row(title, date)'
__slots__ = ()
_fields = ('title', 'date')
def __new__(cls, title, date):
return tuple.__new__(cls, (title, date))
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new Row object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != 2:
raise TypeError('Expected 2 arguments, got %d' % len(result))
return result
def __repr__(self):
return 'Row(title=%r, date=%r)' % self
def _asdict(t):
'Return a new dict which maps field names to their values'
return {'title': t[0], 'date': t[1]}
def _replace(self, **kwds):
'Return a new Row object replacing specified fields with new values'
result = self._make(map(kwds.pop, ('title', 'date'), self))
if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result
def __getnewargs__(self):
return tuple(self)
title = property(itemgetter(0))
date = property(itemgetter(1))
Отсортируйте данные (или копия данных) непосредственно и создайте список dicts впоследствии. Вид с помощью функции, отсортированной с appropiate ключевой функцией (operator.attrgetter, вероятно)
Если Вы в целую вещь краткости:
data = "data from database"
sorted_data = sorted(
[{'title': x.title, 'date': x.created_on} for x in data],
key=operator.itemgetter('date'),
reverse=True)
У меня на самом деле вчера был этот почти точный вопрос, и решил его с помощью поиска . Лучший ответ относился к Вашему вопросу, это:
from operator import itemgetter
list.sort(key=itemgetter('date'), reverse=True)