Это должно сработать. Обратите внимание, что имена столбцов с пробелами в них немного изменены («Product cat.» На «Product.cat.» И т. Д.)
df <- df %>%
mutate(Product.cat. = case_when(nchar(Product.cat.) == 1 ~ paste0(Product.cat.,'mm'),
nchar(Product.cat.) == 2 ~ paste0(Product.cat.,'m'),
TRUE ~ Product.cat.))
Если вы ищете объектно-ориентированный (или доменно-ориентированный подход) подход, тогда третий объект для обработки 'соединения' - совершенно неправильный способ сделать это. Вы можете использовать ILists / Enumerables с методами Add ... для обработки этого следующим образом:
public class Participant
{
private readonly IList<Championship> _championships = new List<Championship>();
public IEnumerable<Championship> Championships
{
get { return _championships; }
}
internal void AddChampionship(Championship championship)
{
if (!_championships.Contains(championship))
_championships.Add(championship);
}
}
public class Championship
{
private readonly IList<Participant> _participants = new List<Participant>();
public IEnumerable<Participant> Participants
{
get { return _participants; }
}
public void AddParticipant(Participant participant)
{
if (_participants.Contains(participant)) return;
_participants.Add(participant);
participant.AddChampionship(this);
}
}
Ключевым моментом здесь является убедиться, что вы управляете отношениями только с одной стороны - например, в этом случае это было бы путем вызова чемпионата .AddParticipant ( )
Вы можете иметь любые отношения, в которых конкретный элемент может иметь несколько элементов, связанных с ним, используя свойства IEnumerable (или какой-либо другой коллекции). В вашем примере это будет выглядеть следующим образом:
class Participant {
public IEnumerable<Championship> Championships {
get {
return _championships;
}
}
private List<Championship> _championships;
}
Некоторые важные вещи, которые нужно иметь в виду:
Всегда делайте это свойство только для чтения. Это иногда сбивает с толку людей, особенно если у вас есть что-то изменяемое, например, ICollection, а не IEnumerable. Создание свойства только для чтения не препятствует модификации коллекции , но изменяет весь список .
Загрузка стратегий - вы заметите, что в примере выше коллекция isn не инициализирован. Обычно вы делаете это либо в конструкторе, либо при первом обращении к свойству (это называется отложенной реализацией) - в общем случае отложенная реализация создает некоторую сложность, но может повысить производительность, особенно если эта коллекция используется не часто или у вас много таких типов. Свойства.
Как правило, хорошей идеей является выбор класса для «удержания» другого класса в случае «многие ко многим» (т. е. у участников есть свойства чемпионатов, но у чемпионатов нет свойств участников или наоборот). Это сокращает объем кода, который вы должны написать, и уменьшает сложность и вашу поверхность с вашей базой данных. Если вызов необходим для другого направления, рассмотрите вызов метода, а не свойство. Помните, что многие ко многим в реляционном смысле не обязательно означают, что Это общий случай использования (как пользователь, я мог бы захотеть добавлять участников в чемпионаты, а не в чемпионаты для участников).
Если ваша коллекция модифицируема, помните, что отправка Save подразумевает, что коллекции под ним также должны быть изменены, если они были изменены. Это может добавить большую сложность (в прошлом я использовал внутренние списки для хранения добавленных / удаленных элементов)
I ' Я не уверен, что это работает для вашего дизайна или требований, но это может быть возможно ...
Очевидно, что отношение многие ко многим легче всего представить с третьим объектом, который управляет отношениями. В вашем случае это будет чемпион чемпионата . Вместо того, чтобы иметь коллекцию в вашем классе участников, которая проводит чемпионаты и наоборот, пусть они держат экземпляр этого третьего класса. Объект championshipparticipant управляет этими отношениями.