упорядоченный обмен на простой коллекции - PullRequest
4 голосов
/ 06 октября 2010

У меня есть метод, который меняет два элемента:

swap( collection['a'], collection['b'] );  // result = 'b', 'a'
swap( collection[0], collection[1] ); // result = collection[1], collection[0]
swap( 0, collection.indexOf(collection[1]) ); // result collection[1] index, 0
  • Метод обмена не может быть изменен.
  • Четыре возможных значения, хранящихся в коллекции: «a», «b», «c», «d»
  • Поменяйте местами, чтобы всегда быть в этом порядке «d», «b»,'a', 'c'
  • Любое из четырех возможных значений может быть или не быть в коллекции

Пожалуйста, помогите мне реализовать этот алгоритм.

Спасибо!

Для тех, кто заботится, это не домашняя работа.

Примеры:

//Example 1:
//collection contains: 'a', 'b', 'c', 'd'
//desired order: 'd', 'b', 'a', 'c'
swap(0, collection.IndexOf(collection['d']));
swap(1, collection.IndexOf(collection['b']));
swap(2, collection.IndexOf(collection['a']));
swap(3, collection.IndexOf(collection['c']));

//Example 2:
//collection contains: 'a', 'b', 'c'
//desired order: 'b', 'a', 'c' 
swap(0, collection.IndexOf(collection['b']));
swap(1, collection.IndexOf(collection['a']));
swap(2, collection.IndexOf(collection['c']));

Ответы [ 3 ]

2 голосов
/ 13 октября 2010

Решение Jerry's C ++ адаптировано к C #:

using System;
using IComparer = System.Collections.IComparer;

class CustomOrder: IComparer
{
    static readonly int[]   positions = { 2, 1, 3, 0 };

    public int Compare( object x, object y )
    {
        return positions[(char)x-'a'].CompareTo( positions[(char)y-'a'] );
    }
}

class Startup
{
    static void Main(string[] args)
    {
        char[]  collection  = {'a', 'b', 'c', 'd'};

        Console.WriteLine( collection );            // abcd
        Array.Sort( collection, new CustomOrder() );
        Console.WriteLine( collection );            // dbac
    }
}
2 голосов
/ 06 октября 2010

По сути, вы ищете сортировку с косвенным сравнением.Т.е. вместо сравнения самих букв вы сравниваете значения, которые они ищут в таблице.Если вы простите синтаксис C ++, общая идея будет выглядеть примерно так:

class my_cmp { 
    static const int positions[] = { 2, 1, 3, 0};
public:
    bool operator<(char a, char b) { 
        return positions[a-'a'] < positions[b-'a'];
    }
}:

std::sort(collection.begin(), collection.end(), my_cmp());

std::sort будет использовать swap для перемещения элементов в коллекции.Хотя синтаксис, очевидно, будет немного отличаться от того, что я помню, когда в последний раз использовал его, та же общая идея должна быть достаточно хорошо применима и к C #.

0 голосов
/ 07 октября 2010

Теперь я понимаю (благодаря тем, кто ответил), что использование настраиваемого IComparer, подобного приведенному ниже, устраняет необходимость использовать своп. Это решение гарантирует порядок и будет работать правильно, когда один из 5 возможных значения отсутствуют.

class CustomOrder : IComparer<Series>
{
    static readonly Dictionary<string, int> dictionary = 
        new Dictionary<string, int>() 
    { 
        {"Excellent", 1}, 
        {"Very Good", 2},
        {"Average", 3},
        {"Bad", 4},
        {"Very Bad", 5}
    };

    public int Compare(Series x, Series y)
    {
        return dictionary[x.Name].CompareTo(dictionary[y.Name]);
    }
}

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Series[] sortedSeries = chart.Series.ToArray();
        Array.Sort(sortedSeries, new CustomOrder());
    } 
}

Старый раствор с использованием свопа (для справки)

Мне это не нравится, но, похоже, это работает. У кого-нибудь есть идеи получше?

int count = collection.Count;

// don't need to swap if there is only one element
if (count > 1)
{
    // have to run once for each letter 
    sortCollection(count);
    sortCollection(count);      
    sortCollection(count);
    sortCollection(count);
}

private void sortCollection(int count)
{
    if (collection.Contains(collection['c']))
    {
        // take care of last element
        collection.Swap(count - 1, collection.IndexOf(collection['c']));
    }
    if (collection.Contains(collection['a']) && collection.Contains(collection['b']))
    {
        // take care of middle elements
        if(collection[1] != collection['b'])
        collection.Swap(collection['a'], collection['b']);
    }
    if (collection.Contains(collection['d']))
    {
        // take care of first element
        if(collection[0] != collection['d'])
        collection.Swap(0, collection.IndexOf(collection['d']));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...