Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с коллекцие фильмов, осторожно, много букв! 
:(
    Опции темы
VeryWell
Дата 15.3.2009, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 15.3.2009

Репутация: нет
Всего: нет



Доброго всем времени суток!
Я только начал работать на C#, но после Delphi очень тяжело =)
Есть задание создать коллекцию фильмов и описать некоторые методы работы ней... Консольное приложение, создаваемое мной использует готовую библиотеку.
Я разбираю запись о фильме, а вот правильно сформировать коллекцию фильмов и переслать её между классами не могу сообразить как в моей задачи реализовать. Буду очень благодарен за помощь! Правда много букв =)

Вот задание:
Имеется текстовый файл, содержащий информацию о фильмах. Файл имеет следующий формат:

"<название фильма>" <режиссер> <год выхода> <список актеров через запятую>

Описание каждого фильма начинается с новой строки.

Пример файла:

"The Shawshank Redemption" Frank Darabont 1994 Tim Robbins, Andy Dufresne, Morgan Freeman, Ellis Boyd 'Red' Redding, Bob Gunton, Warden Norton
"The Godfather" Francis Ford Coppola 1972 Marlon Brando, Don Vito Corleone,    Al Pacino, Michael Corleone

Название фильма заключено в кавычки, год всегда содержит 4 цифры, актеры разделяются запятой. 
Поэтому строка с инфомацией о фильме разбирается однозначно. Имя режиссера гарантированно не содержит 4 цифр ;)

Требуется создать класс для хранения информации о фильме. Назовем его условно FilmInfo (имя для примера, можно называть как угодно). Данный класс должен реализовывать интерфейс IFilmInfo.
Код

     interface IFilmInfo
    {
        int Year { get; } // год выхода
        string Name { get; } // название
        string Director { get; } // режиссер
        StringCollection Actors { get; } // список актеров
    }


Требуется создать класс коллекции для хранения списка фильмов. Назовем его условно MultyKeyedCollection (имя для примера, можно называть как угодно).
Данный класс будет являться реализацией IList, т.е. в него будут добавляться объекты FilmInfo. При добавлении объекта информации о фильме для него автоматически добавляются ключи.


Имя актера будет являться ключем, информация о фильме - значением.
Но один актер может присутствовать в нескольких фильмах сразу, т.е. одному ключу может соответствовать несколько значений.
Также в одном фильме могут быть несколько актеров, т.е. одному значению могут соответствовать несколько ключей.

Создаваемый класс коллекции должен быть универсальным, т.е. быть generic'ом вида:
MultyKeyedCollection<TKey, TValue>, где TKey - тип ключа (в нашем случае это string - имя актера), TValue - тип для значения (в нашем случае это класс с информацией о фильме)

Для удобства дальнейшего использования, на основе универсального класса MultyKeyedCollection создаем унаследованный класс, представляющие именно коллекцию фильмов.
К примеру, так: FilmsCollection : MultyKeyedCollection<string, FilmInfo> {}

В классе MultyKeyedCollection требуется обеспечить следующие возможности:
1. Реализация IList - т.е. все возможности, предоставляемые IList - добавление информации о фильме, доступ по индексу, удаление и т.д.
2. Возможность получения коллекции фильмов по имени актера (ключу) при помощи синтаксиса []. Данная коллекция должна быть объектом этого же класса коллекции фильмов. 

т.е., к примеру, если coll - объект коллекции фильмов, то вызов:
FilmsCollection films = coll["Al Pacino"] должен записать в переменную films список фильмов с Аль Пачино.

Если ключа нет, то должно бросаться соответствующее исключение.

3. Класс MultyKeyedCollection должен также реализовывать интерфейс IListKey<TKey>, добавляющий следующие возможности: 
3.а. функция void Remove(TKey key) - возможность удаления фильмов по ключу (актеру). При удалении ключа (актера) удаляются все фильмы с данным актером.
3.б. функция bool Contains(TKey key) - возвращает, присутствует ли ключ в коллекции, т.е. есть ли в списке фильмы с данным актером 

Наконец, требуется написать парсер для заполнения MultyKeyedCollection информацией из текстового файла (рекомендуется использовать regex'ы).
Данный парсер должен реализовывать интерфейс IFilmsParser<T>, содержащий единственную функцию 
T Parse(string path);
Данная функция возвращает коллекцию, заполненную информацией о фильме.
T - это имя класса коллекции, созданного выше (для примера оно было MultyKeyedCollection)
path - имя исходного файла

Помимо правильности работы будет оцениваться скорость (парсинга, поиска по ключу/значению, удаление и т.п.)

Объявления упомянутых интерфейсов IFilmInfo, IListKey<TKey> и IFilmsParser<T> см. в прилагаемой сборке. Они находятся в пространстве имен FilmsList

Естественно, все создаваемые классы должны иметь модификатор public.

Готовую сборку необходимо оформить в виде dll или exe файла.

Пример того, что нужно сделать:

 
Код

   // Класс для хранения информации о фильме
    public class FilmInfo : IFilmInfo
    {
        
    }

    // Обобщенный класс коллекции с поиском нескольких значений по ключу, реализующий IList и IListKey
    public class MultyKeyedCollection<TKey, TValue> : IList<TValue>, FilmsList.IListKey<TKey>
    {
    }

    // Класс коллекции фильмов
    public class FilmsCollection : MultyKeyedCollection<TKey, TValue>
    {
    }

    // Класс парсера файла с информацией о фильме
    public class FilmsParser : FilmsList.IFilmsParser<FilmsCollection>
    {
        
    }

    // Пример использования
    FilmsParser parser = new FilmsParser();
    FilmsCollection films = parser.Parse(@"c:\films.dat");
    foreach (FilmInfo fi in films)
    {
        Console.WriteLine(fi.Name);
        foreach (string a in fi.Actors)
            Console.WriteLine(a);
    }

    FilmsCollection coll = films["Marlon Brando"];


---------------------------------------------------------------------------------------------
Вот то что сделал я:

Код

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.Specialized;
using FilmsList;


namespace Rezult
{
    

    // Класс для хранения информации о фильме
    public class FilmInfo : FilmsList.IFilmInfo
    {
        public StringCollection Actors;
        public string Director;
        public string Name;
        public int Year;

        public FilmInfo (StringCollection Actors, string Director, string Name, int Year)
        {
            this.Year = Year;
            this.Name = Name;
            this.Director = Director;
            this.Actors = Actors;
        }

        #region Члены IFilmInfo

        System.Collections.Specialized.StringCollection FilmsList.IFilmInfo.Actors
        {
            get { throw new NotImplementedException(); }
        }

        string FilmsList.IFilmInfo.Director
        {
            get { throw new NotImplementedException(); }
        }

        string FilmsList.IFilmInfo.Name
        {
            get { throw new NotImplementedException(); }
        }

        int FilmsList.IFilmInfo.Year
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }

    // Обобщенный класс коллекции с поиском нескольких значений по ключу, реализующий IList и IListKey
    public class MultyKeyedCollection<TKey, TValue> : IList<TValue>, FilmsList.IListKey<TKey>
    {

        #region Члены IList<TValue>

         int IList<TValue>.IndexOf(TValue item)
        {
            throw new NotImplementedException();
        }

        void IList<TValue>.Insert(int index, TValue item)
        {
            throw new NotImplementedException();
        }

        void IList<TValue>.RemoveAt(int index)
        {
            throw new NotImplementedException();
        }

        TValue IList<TValue>.this[int index]
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        #endregion

        #region Члены ICollection<TValue>

        void ICollection<TValue>.Add(TValue item)
        {
            throw new NotImplementedException();
        }

        void ICollection<TValue>.Clear()
        {
            throw new NotImplementedException();
        }

        bool ICollection<TValue>.Contains(TValue item)
        {
            throw new NotImplementedException();
        }

        void ICollection<TValue>.CopyTo(TValue[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }

        int ICollection<TValue>.Count
        {
            get { throw new NotImplementedException(); }
        }

        bool ICollection<TValue>.IsReadOnly
        {
            get { throw new NotImplementedException(); }
        }

        bool ICollection<TValue>.Remove(TValue item)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Члены IEnumerable<TValue>

        IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Члены IEnumerable

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Члены IListKey<TKey>

        bool IListKey<TKey>.Contains(TKey key)
        {
            throw new NotImplementedException();
        }

        void IListKey<TKey>.Remove(TKey key)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    // Класс коллекции фильмов
    public class FilmsCollection : MultyKeyedCollection<string, FilmInfo>
    {
        public NameValueCollection Films;
        public FilmsCollection(NameValueCollection Films)
        {
            this.Films = Films;
        }
    }

    // Класс парсера файла с информацией о фильме
    public class FilmsParser : FilmsList.IFilmsParser<FilmsCollection>
    {

        #region Члены IFilmsParser<FilmsCollection>

        FilmsCollection FilmsList.IFilmsParser<FilmsCollection>.Parse(string path)
        {
            StreamReader film = new StreamReader(path);

                Regex common = new Regex("^\"(?<title>.+)\"\\s*(?<director>\\D+)\\s*(?<year>\\d{4})\\s*(?<actors>.+)", RegexOptions.Compiled);
                Regex r_actor = new Regex("(?<actor>.+)\\,*\\s*", RegexOptions.Compiled);

                Match m;
                string str;
                StringCollection actorscollection = new StringCollection();
                while ((str = film.ReadLine()) != null)
                {
                    m = common.Match(str);
                    
                    string filmname = string.Format("{0}", m.Groups[1]);
                    string director = string.Format("{0}", m.Groups[2]);
                    int year = (int)(object)string.Format("{0}", m.Groups[3]);
                    string actors = string.Format("{0}", m.Groups[4]);
                    for (m = r_actor.Match(actors); m.Success; m = m.NextMatch())
                    {
                         actorscollection.Add(string.Format("{0}", m.Groups[1]));
                    }
                    FilmInfo Value = new FilmInfo(actorscollection, director, filmname, year);
                    for(int i = 0;i<=actorscollection.Count;++i) 
                    {
                        
                    }
                }
               
                film.Close();
                throw new NotImplementedException();
            }
        

        #endregion
    }



Код

    class Program
    {
        static void Main(string[] args)
        {
            /* Пример использования
FilmsParser parser = new FilmsParser();
FilmsCollection films = parser.Parse(@"c:\films.dat");
foreach (FilmInfo fi in films)
{
    Console.WriteLine(fi.Name);
    foreach (string a in fi.Actors)
        Console.WriteLine(a);
}

FilmsCollection coll = films["Marlon Brando"];
 */
        }
    }
}



Необходимо теперь сформировать коллекцию в парсере и закинуть её в MultyKeyCollection, как это сделать?

Копирую все, просто не знаю что лишее.
За одно то, что здесь разбирутся наверное пиво будут требовать =))


Модератор: Не забывайте обрамлять код тэгом code

Это сообщение отредактировал(а) Partizan - 15.3.2009, 20:16
PM MAIL   Вверх
arilou
Дата 18.3.2009, 01:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Дело было вечером, делать было нечего  smile 

1. Создаем класс MultiKeyCollection<TKey, TValue> и реализуем в нем IList<TValue> методом агрегации

Код

class MultiKeyCollection<TKey, TValue> : IList<TValue>
    {
        List<TValue> _values = new List<TValue>();

        #region IList<TValue> Members

        public int IndexOf(TValue item)
        {
            return _values.IndexOf(item);
        }

        public void Insert(int index, TValue item)
        {
            _values.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            _values.RemoveAt(index);
        }

        public TValue this[int index]
        {
            get
            {
                return _values[index];
            }
            set
            {
                _values[index] = value;
            }
        }

        #endregion

        #region ICollection<TValue> Members

        public void Add(TValue item)
        {
            _values.Add(item);
        }

        public void Clear()
        {
            _values.Clear();
        }

        public bool Contains(TValue item)
        {
            return _values.Contains(item);
        }

        public void CopyTo(TValue[] array, int arrayIndex)
        {
            _values.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return _values.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(TValue item)
        {
            return _values.Remove(item);
        }

        #endregion

        #region IEnumerable<TValue> Members

        public IEnumerator<TValue> GetEnumerator()
        {
            return _values.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion
    }


2. Добавляем в MultiKeyCollection словарь, который будет хранить списки Value по Key:

Код

Dictionary<TKey, List<TValue>> _valuesByKey = new Dictionary<TKey, List<TValue>>();


3. Добавляем интерфейс IKeyProvider<TKey>

Код

    interface IKeyProvider<TKey>
    {
        TKey[] GetKeys();
    }


Судя по всему, это аналог того, что у тебя называется  FilmsList.IListKey<TKey>, но его кода ты не привел, поэтому я додумал сам.

4. Добавляем простой класс с инфой о фильме

Код

    class FilmInfo
    {
        public string Title { get; set; }
        public List<string> Actors { get; private set; }

        public FilmInfo()
        {
            Actors = new List<string>();
        }
    }



5. Имплементим в нем IKeyProvider

Код

    class FilmInfo : IKeyProvider<string>
    {
        public string Title { get; set; }
        public List<string> Actors { get; private set; }

        public FilmInfo()
        {
            Actors = new List<string>();
        }

        #region IKeyProvider<string> Members

        public string[] GetKeys()
        {
            return Actors.ToArray();
        }

        #endregion
    }


6. Накладываем ограничение на typename TValue следующим образом

Код

class MultiKeyCollection<TKey, TValue> : IList<TValue> where TValue: IKeyProvider<TKey>


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

7. Добавляем вспомогательные методы для синхронизации _values и _valuesByKey (Add и Remove)

Код

    void _Add(TValue value)
        {
            TKey[] keys = value.GetKeys();

            foreach (var key in keys)
            {
                List<TValue> keyValues;
                _valuesByKey.TryGetValue(key, out keyValues);

                // если в _valuesByKey еще не было записи с ключом key, то добавляем для нее пустой список
                if (keyValues == null)
                {
                    keyValues = new List<TValue>();
                    _valuesByKey.Add(key, keyValues);
                }

                // чтоб не было дубликатов
                if(!keyValues.Contains(value))
                    keyValues.Add(value);
            }
        }

        void _Remove(TValue value)
        {
            TKey[] keys = value.GetKeys();

            // удаляем из списка values, связанного с каждым ключом, возвращаемым через value.GetKeys()
            foreach (var key in keys)
            {
                List<TValue> keyValues;
                _valuesByKey.TryGetValue(key, out keyValues);

                if (keyValues != null)
                {
                    keyValues.Remove(value);
                }
            }
        }
 


8. Добавляем индексатор this[TKey], возвращающий IEnumerable<TValue>

Код

        public IEnumerable<TValue> this[TKey key]
        {
            get { return _valuesByKey[key]; }
        }


9. Расширяем имплементацию методов, модифицирующих список _values с тем, чтобы синхронизировать его со словарем _valuesByKey, вызывая _Add или _Remove по необходимости.

Класс MultiKeyCollection теперь выглядит следующим образом:

Код

    class MultiKeyCollection<TKey, TValue> : IList<TValue> where TValue: IKeyProvider<TKey>
    {
        Dictionary<TKey, List<TValue>> _valuesByKey = new Dictionary<TKey, List<TValue>>();

        // IList implementation 

        List<TValue> _values = new List<TValue>();

        void _Add(TValue value)
        {
            TKey[] keys = value.GetKeys();

            foreach (var key in keys)
            {
                List<TValue> keyValues;
                _valuesByKey.TryGetValue(key, out keyValues);

                // если в _valuesByKey еще не было записи с ключом key, то добавляем для нее пустой список
                if (keyValues == null)
                {
                    keyValues = new List<TValue>();
                    _valuesByKey.Add(key, keyValues);
                }

                // чтоб не было дубликатов
                if(!keyValues.Contains(value))
                    keyValues.Add(value);
            }
        }

        void _Remove(TValue value)
        {
            TKey[] keys = value.GetKeys();

            // удаляем из списка values, связанного с каждым ключом, возвращаемым через value.GetKeys()
            foreach (var key in keys)
            {
                List<TValue> keyValues;
                _valuesByKey.TryGetValue(key, out keyValues);

                if (keyValues != null)
                {
                    keyValues.Remove(value);
                }
            }
        }

        public IEnumerable<TValue> this[TKey key]
        {
            get { return _valuesByKey[key]; }
        }

        #region IList<TValue> Members

        public int IndexOf(TValue item)
        {
            return _values.IndexOf(item);
        }

        public void Insert(int index, TValue item)
        {
            _values.Insert(index, item);
            _Add(item);
        }

        public void RemoveAt(int index)
        {
            TValue item = _values[index];
            _Remove(item);
            _values.RemoveAt(index);
        }

        public TValue this[int index]
        {
            get
            {
                return _values[index];
            }
            set
            {
                _values[index] = value;
            }
        }

        #endregion

        #region ICollection<TValue> Members

        public void Add(TValue item)
        {
            _values.Add(item);
            _Add(item);
        }

        public void Clear()
        {
            _values.Clear();
            _valuesByKey.Clear();
        }

        public bool Contains(TValue item)
        {
            return _values.Contains(item);
        }

        public void CopyTo(TValue[] array, int arrayIndex)
        {
            _values.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return _values.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(TValue item)
        {
            _Remove(item);
            return _values.Remove(item);
        }

        #endregion

        #region IEnumerable<TValue> Members

        public IEnumerator<TValue> GetEnumerator()
        {
            return _values.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion
    }



10. Теперь добавим для удобства override ToString() в FilmInfo
Код

        public override string ToString()
        {
            return string.Format("Фильм \"{0}\"", Title);
        }


11. И наконец, добавим тестовый пример.

Код

class Program
    {
        static void Main(string[] args)
        {
            string[] actors = { "Actor1", "Actor2", "Actor3" };

            FilmInfo[] fi = new FilmInfo[]
            {
                new FilmInfo() { Title = "Film1", Actors = {actors[0], actors[1], actors[2]} }, 
                new FilmInfo() { Title = "Film2", Actors = {actors[0], actors[1], actors[2]} }, 
                new FilmInfo() { Title = "Film3", Actors = {actors[0]} }, 
                new FilmInfo() { Title = "Film4", Actors = {actors[1]} }, 
                new FilmInfo() { Title = "Film5", Actors = {actors[2]} }, 
            };

            MultiKeyCollection<string, FilmInfo> coll = new MultiKeyCollection<string, FilmInfo>();
            foreach (var item in fi)
            {
                coll.Add(item);
            }

            Console.WriteLine("Выводим все фильмы");

            foreach (var film in coll)
            {
                Console.WriteLine(film);
            }

            Console.WriteLine("Выводим фильмы каждого актёра");
            foreach (var actor in actors)
            {
                Console.WriteLine("Актер {0} участвует в: ", actor);
                foreach (var actorFilm in coll[actor])
                {
                    Console.WriteLine("   {0}", actorFilm);
                }
            }
            Console.ReadLine();
        }


Рабочий код приаттачен. Демонстрируется решение первой половины поставленой задачи -- создание коллекции, поддерживающей хранение объектов одновременно по нескольким ключам. По скорости даже не знаю, вроде как оптимально. 

Остальное ты вполне в состоянии сделать сам. 

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  ConsoleApplication1.zip 3,79 Kb


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1254 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.