Отсортируйте Список <T> использующий выражения запроса

Сортировка документов в firebase firebase выполняется firebase. Если вы хотите получить документ на основе времени создания, вам нужно создать поле, скажем, время и сохранить serverTimestamp. Теперь при запросе документа вы можете использовать предложение orderBy, чтобы получить документ.

Чтобы добавить документ:

this.afs.collection('values').add({
time:firebase.firestore.FieldValue.serverTimestamp()
});

. Чтобы получить документ:

this.afs.collection('values',ref=>ref.OrderBy('time','desc')).valueChanges();

, это даст вам заметку о документах. По подписке вы получите массив документов, где первый элемент массива является последним добавленным документом

13
задан svick 22 January 2013 в 16:08
поделиться

7 ответов

OrderBy расширение LINQ, которое производит новую последовательность. Для упорядочивания существующей последовательности, необходимо добавить дополнительный метод, или два... затем можно использовать:

PersonList.Sort(p => p.Attributes.Find(
  s => s.Name == mySortAttribute).Value);

public static class ListExtensions {
  public static void Sort<TSource, TValue>(
    this List<TSource> source,
    Func<TSource, TValue> selector)
  {
    var comparer = Comparer<TValue>.Default;
    source.Sort((x, y) => comparer.Compare(selector(x), selector(y)));
  }
  public  static void SortDescending<TSource, TValue>(
    this List<TSource> source,
    Func<TSource, TValue> selector)
  {
    var comparer = Comparer<TValue>.Default;
    source.Sort((x, y) => comparer.Compare(selector(y), selector(x)));
  }
}
9
ответ дан 1 December 2019 в 22:08
поделиться

Почему Вы не используете словарь значения ключа вместо своего Списка <PersonAttribute>? Это подошло бы лучше, я думаю и делаю все остальное легче.

Обновление - как это:

public class Person
{
  public Dictionary<string, string> Attributes = new Dictionary<string,string>();
}

List<Person> people = new List<Person>();

Person rebecca = new Person();
rebecca.Attributes["Age"] = "32";
rebecca.Attributes["FirstName"] = "Rebecca";
rebecca.Attributes["LastName"] = "Johnson";
rebecca.Attributes["Gender"] = "Female";
people.Add(rebecca);

var PeopleInAgeOrder = people.OrderBy(p => p.Attributes["Age"]);
5
ответ дан 1 December 2019 в 22:08
поделиться

Это предполагает, что класс Атрибута реализует IComparable, или сделал, чтобы хороший ToString функционировал (я надеюсь).

var list = personList.OrderBy(p => p.Attributes.FirstOrDefault(a => a.Name == "Age"))

Иначе синтаксис становится более замысловатым:

var list = personList
            .OrderBy(p => 
                     p.Attributes.FirstOrDefault(a => a.Name == "Age") == null ?
                     "" : p.Attributes.First(a => a.Name == "Age").Value
            );

Я также предполагаю, что у Вас есть одно значение для каждого ключа - иначе у Вас должен был бы быть более умный код... ;-)

1
ответ дан 1 December 2019 в 22:08
поделиться

Могло случиться так, что Ваш синтаксис является неправильным? Ваше свойство называют Атрибутами, но Вашим использованием чего-то названного ObjectSettings в коде? Или то, что опечатка.

Если это - затем Ваш код, выглядит хорошо, если не все экземпляры Человека не имеют Атрибут, Вы пытаетесь заказать, в этом случае, Вы получили бы исключение.

Править: Кроме того, вместо использования Находят, пытаются использовать Сначала.

PersonList.OrderBy(p => p.Attributes.First(a => a.Name == "Age").Value)
0
ответ дан 1 December 2019 в 22:08
поделиться

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

    List<Person> personList = new List<Person>();
    Random rand = new Random();

    //generate 50 random persons
    for (int i = 0; i < 50; i++)
    {
        Person p = new Person();
        p.Attributes = new List<PersonAttribute>();
        p.Attributes.Add(new PersonAttribute() { ID = 8, Name = "Age", Value = rand.Next(0, 100).ToString() });
        p.Attributes.Add(new PersonAttribute() { ID = 10, Name = "Name", Value = rand.Next(0, 100).ToString() });
        personList.Add(p);
    }

    var finalList = personList.OrderBy(c => c.Attributes.Find(a => a.Name == "Age").Value).ToList();
0
ответ дан 1 December 2019 в 22:08
поделиться

Я знаю, что это старый пост, но я подумал, что выложу сравнитель, который я нашел некоторое время назад, на случай, если он понадобится кому-то еще.

public class GenericComparer<T> : IComparer<T>
 {
     public string SortExpression { get; set; }
     public int SortDirection { get; set; } // 0:Ascending, 1:Descending

     public GenericComparer(string sortExpression, int sortDirection)
     {
         this.SortExpression = sortExpression;
         this.SortDirection = sortDirection;
     }
     public GenericComparer() { }

     #region IComparer<T> Members
     public int Compare(T x, T y)
     {
         PropertyInfo propertyInfo = typeof(T).GetProperty(SortExpression);
         IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
         IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);

         if (SortDirection == 0)
         {
             return obj1.CompareTo(obj2);
         }
         else return obj2.CompareTo(obj1);
     }
     #endregion
 }

Использование

List<MyObject> objectList = GetObjects(); /* from your repository or whatever */
objectList.Sort(new GenericComparer<MyObject>("ObjectPropertyName", (int)SortDirection.Descending));
dropdown.DataSource = objectList;
dropdown.DataBind();

Вы можете перегрузить конструктор, чтобы он принял перечисление SortDirection. Я этого не делал, потому что класс находится в библиотеке без ссылки на System.Web.

8
ответ дан 1 December 2019 в 22:08
поделиться

Некоторые случаи, которые необходимо учитывать:

  • Поскольку ваш атрибут находится в строке, возраст "30" и "3" будет упорядочен до возраста of "4"
  • Атрибут может не существовать

Если вы создаете этот класс методов расширения:

public static class ListExtenstions
{
    public static List<Person> OrderList(this List<Person> list, string attributeName, PersonAttribute defaultAttribute)
    {
        return OrderList(list, attributeName, defaultAttribute, x => x);
    }

    public static List<Person> OrderList<T>(this List<Person> list, string attributeName, PersonAttribute defaultAttribute, Func<string, T> convertion)
    {
        return list.OrderBy(x => convertion((x.Attributes.FirstOrDefault(y => y.Name == attributeName) ?? defaultAttribute).Value)).ToList();

        // Query Syntax
        //return
        //    (from p in list
        //     let attribute = p.Attributes.FirstOrDefault(a => a.Name == attributeName) ?? defaultAttribute
        //     orderby attribute.Value
        //     select p).ToList();
    }
}

Затем вы можете правильно отсортировать список следующим образом:

List<Person> persons = ...
...
PersonAttribute defaultAttribute = new PersonAttribute() { Value = "0" };
var ordered = persons.OrderList("Age", defaultAttribute, x => Convert.ToInt32(x));

Это даст правильный порядок сортировки. {{1 }} Если атрибут будет присутствовать всегда, вы можете удалить defaultAttribute .

Чтобы отсортировать "Имя", просто введите:

List<Person> persons = ...
...
PersonAttribute defaultAttribute = new PersonAttribute() { Value = String.Empty };
var ordered persons.OrderList("Name", defaultAttribute);
0
ответ дан 1 December 2019 в 22:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: