Сортируйте все границы, затем возьмите все пары, у которых за концом границы следует начало границы.
def mergeOverlapping(initialranges):
def allBoundaries():
for r in initialranges:
yield r[0], True
yield r[1], False
def getBoundaries(boundaries):
yield boundaries[0][0]
for i in range(1, len(boundaries) - 1):
if not boundaries[i][1] and boundaries[i + 1][1]:
yield boundaries[i][0]
yield boundaries[i + 1][0]
yield boundaries[-1][0]
return getBoundaries(sorted(allBoundaries()))
Хм, не так красиво, но по крайней мере было весело писать!
РЕДАКТИРОВАТЬ: Спустя годы, после взрыва, я понял, что мой код был неправильным! Это новая версия просто для удовольствия:
def mergeOverlapping(initialRanges):
def allBoundaries():
for r in initialRanges:
yield r[0], -1
yield r[1], 1
def getBoundaries(boundaries):
openrange = 0
for value, boundary in boundaries:
if not openrange:
yield value
openrange += boundary
if not openrange:
yield value
def outputAsRanges(b):
while b:
yield (b.next(), b.next())
return outputAsRanges(getBoundaries(sorted(allBoundaries())))
По сути, я отмечаю границы с помощью -1 или 1, а затем сортирую их по значению и выводу только тогда, когда баланс между открытыми и закрытыми скобками равен нулю.
Я нашел решение благодаря этой публикации на форуме . По сути, вам необходимо иметь прототип функции, прежде чем вы сможете использовать для него «friend» в классе, однако вам также необходимо объявить класс, чтобы правильно определить прототип функции. Следовательно, решение состоит в том, чтобы иметь два прототипа определения (функции и класса) вверху. Следующий код компилируется под всеми тремя компиляторами:
#include <iostream>
using namespace std;
//added lines below
template<typename T> class Container;
template<typename T> Container<T> operator+ (Container<T>& lhs, Container<T>& rhs);
template <typename T>
class Container
{
friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs);
public: void setobj(T ob);
T getobj();
private: T obj;
};
template <typename T>
void Container<T>::setobj(T ob)
{
obj = ob;
}
template <typename T>
T Container<T>::getobj()
{
return obj;
}
template <typename T>
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs)
{
Container<T> temp;
temp.obj = lhs.obj + rhs.obj;
return temp;
}
int main()
{
Container<int> a, b;
a.setobj(5);
b.setobj(6);
Container<int> c = a + b;
cout << c.getobj() << endl;
return 0;
}
template <typename T>
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs)
Здесь следует удалить «<>» после оператора +
, поскольку вы просто объявляете новый шаблон, а не специализирующийся на общем. Также как минимум g ++
хочет видеть объявление шаблона перед объявлением друга, поэтому его нужно переместить перед объявлением Контейнера
. Таким образом, работает следующий порядок объявлений:
// forward declaration of Container<T>
template <typename T>
class Container;
template <typename T>
Container<T> operator+(Container<T>& lhs, Container<T>& rhs)
{ ... }
template <typename T>
class Container
{
friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs);
...
};
Я попробовал это в GCC и заставил его скомпилировать и запустить с небольшими изменениями. Чтобы GCC был доволен, мне пришлось внести два изменения.
Одно из них - объявление функции шаблона друга. Это собственное объявление шаблона, отдельное от класса, поэтому я использовал U вместо класса контейнера 'T. Я также избавился от <> после оператора +. Я не думаю, что они вам понадобятся, если вы не пишете специализацию шаблона.
template<typename U>
friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs);
Во-вторых, строка
Container<int>& c = a + b;
не работает с GCC, потому что вы просите сохранить ссылку на временный (результат дополнения). Я удалил амперсанд, чтобы было место для хранения результата.
Я только что видел ваш пост, он также работает из-за предварительных объявлений. Думаю, я все равно опубликую это как альтернативу, которая их не требует. Конечно, я тестировал только в GCC ...
Одним из них было объявление функции шаблона друга. Это собственное объявление шаблона, отдельное от класса, поэтому я использовал U вместо класса контейнера 'T. Я также избавился от <> после оператора +. Я не думаю, что они вам понадобятся, если вы не пишете специализацию шаблона.
template<typename U>
friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs);
Во-вторых, строка
Container<int>& c = a + b;
не работает с GCC, потому что вы просите сохранить ссылку на временный (результат дополнения). Я удалил амперсанд, чтобы было место для хранения результата.
Я только что видел ваш пост, он также работает из-за предварительных объявлений. Думаю, я все равно опубликую это как альтернативу, которая их не требует. Конечно, я тестировал только в GCC ...
Одним из них было объявление функции шаблона друга. Это собственное объявление шаблона, отдельное от класса, поэтому я использовал U вместо класса контейнера 'T. Я также избавился от <> после оператора +. Я не думаю, что они вам понадобятся, если вы не пишете специализацию шаблона.
template<typename U>
friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs);
Во-вторых, строка
Container<int>& c = a + b;
не работает с GCC, потому что вы просите сохранить ссылку на временный (результат дополнения). Я удалил амперсанд, чтобы было место для хранения результата.
Я только что видел ваш пост, он также работает из-за предварительных объявлений. Думаю, я все равно опубликую это как альтернативу, которая их не требует. Конечно, я тестировал только в GCC ...
поэтому я использовал U вместо класса контейнера T. Я также избавился от <> после оператора +. Я не думаю, что они вам понадобятся, если вы не пишете специализацию шаблона. template<typename U>
friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs);
Во-вторых, строка
Container<int>& c = a + b;
не работает с GCC, потому что вы просите сохранить ссылку на временный (результат дополнения). Я удалил амперсанд, чтобы было место для хранения результата.
Я только что видел ваш пост, он также работает из-за предварительных объявлений. Думаю, я все равно опубликую это как альтернативу, которая их не требует. Конечно, я тестировал только в GCC ...
поэтому я использовал U вместо класса контейнера T. Я также избавился от <> после оператора +. Я не думаю, что они вам понадобятся, если вы не пишете специализацию шаблона. template<typename U>
friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs);
Во-вторых, строка
Container<int>& c = a + b;
не работает с GCC, потому что вы просите сохранить ссылку на временный (результат дополнения). Я удалил амперсанд, чтобы было место для хранения результата.
Я только что видел ваш пост, он также работает из-за предварительных объявлений. Думаю, я все равно опубликую это как альтернативу, которая их не требует. Конечно, я тестировал только в GCC ...
повторно просим сохранить ссылку на временную (результат добавления). Я удалил амперсанд, чтобы было место для хранения результата.Я только что видел ваш пост, он также работает из-за предварительных объявлений. Думаю, я все равно опубликую это как альтернативу, которая их не требует. Конечно, я тестировал только в GCC ...
повторно просим сохранить ссылку на временную (результат добавления). Я удалил амперсанд, чтобы было место для хранения результата.Я только что видел ваш пост, он также работает из-за предварительных объявлений. Думаю, я все равно опубликую это как альтернативу, которая их не требует. Конечно, я тестировал только в GCC ...
'operator +' не является функцией-членом и не является шаблоном. Это просто оператор +, который принимает шаблонные параметры. '
template <typename T>
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs)
Вам лучше определить функцию непосредственно в классе. Кроме того, вы должны передать параметры как ссылки const
.
template <typename T>
class Container
{
public:
friend Container operator+ (Container const & lhs, Container const & rhs)
{
// ...
}
};