powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Scala : поджать списочек.
19 сообщений из 19, страница 1 из 1
Scala : поджать списочек.
    #40043298
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот приплыла идея.
Есть такой монотонный список чисал. Заданный в оригинале строкой.

Код: sql
1.
'12,13,14,15,16,21,22,23,48,51,52,53'



Надо его "поджать". Сделать нечто вроде.

Код: sql
1.
'12-15,21-23,48,51-53'



Поскольку наркотик ФП уже проник в меня я думаю как-бы я это решал.
Классическое императивное решение - это создать некий автомат с состоянием
который пробежит от начала строки до конца и будет формировать структуры
типа Integer или Range на выходе. Но тут надо смотреть на 2-3 шага вперед.
А это неудобно в автоматах. +Еще эти пограничные кейсы. О которых думать противно.

Хочется уже это сделать на reduce/fold/collect.
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043314
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
Но тут надо смотреть на 2-3 шага вперед

после получения очередной лексемы из потока вперёд смотреть незачем
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043324
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вроде вообще ни один парсер никогда "вперед" не смотрит. Нормальный парсер хранит одно (обычно) предыдущее значение и изредко его откатывает.

похоже mayton'у "наркотик ФП уже проник в меня" настолько, что он конечные автоматы позабыл напрочь )))
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043325
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чортовы наркотики
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043340
chpasha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
про скалу не знаю, если где натупил, соррян

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
public List<Range> compact(String values)
	{
		String[] strings = values.split(",");
		Range currentRange = null;
		List<Range> ranges = new ArrayList<>();
		for (String string : strings)
		{
			Integer currentValue = Integer.parseInt(string);
			if (currentRange == null || currentValue - currentRange.to > 1)
			{
				currentRange = new Range(currentValue, currentValue);
				ranges.add(currentRange);
			}
			else
			{
				currentRange.to = currentValue;
			}

		}
		return ranges;
	}

	public List<Range> compactFunc(String values)
	{
		String[] strings = values.split(",");
		return Arrays.stream(strings)
					 .map(Integer::valueOf)
					 .collect(ArrayList::new, this::accumulate, (l1, l2) -> {});
	}

	private void accumulate(List<Range> range, Integer val)
	{
		if (range.isEmpty() || val - range.get(range.size() - 1).to > 1)
		{
			range.add(new Range(val, val));
		}
		else
		{
			range.get(range.size() - 1).to = val;
		}
	}


compact("12,13,14,15,16,21,22,23,48,51,52,53").forEach(System.out::println);

compactFunc("12,13,14,15,16,21,22,23,48,51,52,53").forEach(System.out::println);


12-16
21-23
48
51-53
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043359
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
object D extends App {
  val str = "12,13,14,15,16,21,22,23,48,51,52,53"
  case class Range(start: Int, end: Int)
  private def handleNumber(num: Int, ranges: List[Range]) = {
    val latest = ranges.headOption
    val openStart = latest.map(_.start).getOrElse(-1)
    val openEnd = latest.map(_.end).getOrElse(-1)
    if (openStart == -1) {
      List(Range(start = num, end = num))
    } else if (num == openEnd + 1) {
      latest.get.copy(end = num) +: ranges.tail
    } else {
      Range(start = num, end = num) +: ranges
    }
  }

  val result = str.split(",").map(_.trim).foldLeft(List.empty[Range]){
    (accum, num) => handleNumber(num.toInt, accum)
  }.reverse
  println(result)
}



По факту та же стейт машина - вид в профиль
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043361
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chpasha, спасибо. А можно ли как-то еще уменьшить объем кода? Просто то императивное решение которое
я себе представлял все еще компактнее чем решение с stream/collect.
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043365
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если совсем буков жалко то вот так -

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
object D extends App {
  val str = "12,13,14,15,16,21,22,23,48,51,52,53"
  case class Range(start: Int, end: Int)
  private def handleNumber(ranges: List[Range], num: Int) = {
    val latest = ranges.headOption
    val openEnd = latest.map(_.end).getOrElse(-1)
    if (openEnd == -1) {
      List(Range(num, num))
    } else if (num == openEnd + 1) {
      latest.get.copy(end = num) +: ranges.tail
    } else {
      Range(num, num) +: ranges
    }
  }

  val result = str.split(",").map(_.trim.toInt).foldLeft(List.empty[Range])(handleNumber).reverse
  println(result)
}
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043367
chpasha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
компактнее чем решение с stream/collect.
там же оба решения, ты заметил?
я не знаю как еще упростить - весь код это по сути только метод accumulate, остальное предварительные расшаркивания
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043370
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник, паша,

спасибо друзья.
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043392
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
(раскачиваясь взад-вперед)

Не нравится мне этот метод.

Код: java
1.
private def handleNumber(ranges: List[Range], num: Int) = {


Он написан ... как бы это сказать... не в духе ФП. Он - модифицирует свой собственный аргумент.
Возможно это контракт коллектора?

Можно ли переписать с reduce? Понимаю что накладные будут.

Ну ... это так. Ворчу просто.

Ворчун я.
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043398
SpringMan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вообще можно как-то так, если память/процессор не жалко:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  val result = "12,13,14,15,16,21,22,23,48,51,52,53".split(",")
    .map(_.toInt)
    .zipWithIndex
    .groupBy { case (value, index) => value - index }
    .values.toSeq
    .sortBy(_.head._1)
    .map(pairs => pairs.map(_._1))
    .map(arrays => if (arrays.length != 1) s"${arrays.head}-${arrays.last}" else s"${arrays.head}")
    .mkString(",")
  println(result)
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043405
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton

Он написан ... как бы это сказать... не в духе ФП. Он - модифицирует свой собственный аргумент.

Нет, там ничего не меняется. Объекты новые создаются, это да, но по минимуму. Самое что ни на есть тру ФП

mayton

Можно ли переписать с reduce?

Можно, но это тот же fold. И оба в конце концов сводятся к рекурсивному методу handleNumber

mayton

Понимаю что накладные будут.

На самом деле не такие огромные, списки не копируются а элементы хвоста и более того шарятся, оставаясь при этом иммутабл
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043419
SpringMan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вариация на тему ренжей, только через Seq-и:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
  val result = "12,13,14,15,16,21,22,23,48,51,52,53".split(",")
    .map(_.toInt)
    .foldLeft(Seq[Seq[Int]]()) { case (total, currentValue) =>
      if (total.lastOption.flatMap(_.lastOption).exists(_ + 1 == currentValue)) {
        total.init :+ (Seq(total.last.head) :+ currentValue)
      } else {
        total :+ Seq(currentValue)
      }
    }
    .map(array => if (array.length != 1) s"${array.head}-${array.last}" else s"${array.head}")
    .mkString(",")
  println(result)
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043425
SpringMan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тут в общем выбор: иммутабельность или затраты на память
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40043505
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SpringMan, спасибо. Уже есть пища для размышлений.
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40044142
andreykaT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кто то решил прокачать скилы гадилити?
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40044146
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я не знаю что это.

Просто, в тему Прохоровских лотерейных билетов.
...
Рейтинг: 0 / 0
Scala : поджать списочек.
    #40044148
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Отчот большой был. Я хотел его "пожать".

Как Дима из команды "Так-То". Кто-то говорит телефон посеял. А я его "пожал".
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Scala : поджать списочек.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]