Фильтровать на функциональных языках с оригинальными нефильтрованными элементами? - PullRequest
4 голосов
/ 04 октября 2011

Я хочу вернуть массив, который отображает некоторые отфильтрованные элементы - но я хочу сохранить неотфильтрованные элементы там, где они есть.т.е. есть ли простой способ сделать это?:

array
.filter(
  function(element){
    // some test
  }
)
.map(
  function(element){
    // some mapping
  }
)

Самое близкое решение, которое я придумала, это что-то вроде:

array
.map(
  function(value, index){
    if (<test>) {
      return <mapping>(value);
    }
  }
)

, но я чувствую это нескольконарушает дух функционального программирования.

Я не прошу конкретную языковую реализацию, хотя пример в Scala или JavaScript был бы хорош.

РЕДАКТИРОВАТЬ: Вот конкретный пример того, что яищу:

[1,2,3,4,11,12]

Отображение всех элементов в элемент * 10, для всех элементов в массиве, которые больше 10, должно привести к

[1,2,3,4,110,120]

EDIT2: Я прошу прощения за использованиеслово "мутировать".Я не имел в виду видоизменять исходный массив - я больше думал о том, чтобы поменять копию массива.

Ответы [ 7 ]

3 голосов
/ 04 октября 2011

Это на самом деле не будет работать, если вы используете изменяемую коллекцию.Но вы можете использовать transform в Scala:

scala> val a = Array(1,2,3,4,11,12)
a: Array[Int] = Array(1, 2, 3, 4, 11, 12)

scala> a.transform {i => if(i > 10) i * 10 else i}
res10: scala.collection.mutable.WrappedArray[Int] = WrappedArray(1, 2, 3, 4, 110, 120)

edit: Если вы хотите, чтобы фильтр и карта были разделены, используйте view:

scala> a
res22: Array[Int] = Array(1, 2, 3, 4, 11, 12)

scala> a.view.filter(_ > 10).transform(_ * 10)
res23: scala.collection.mutable.IndexedSeqView[Int,Array[Int]] = SeqViewF(...)

scala> a
res24: Array[Int] = Array(1, 2, 3, 4, 110, 120)
2 голосов
/ 04 октября 2011

Хотя эти виды операций в принципе возможны, библиотека Scala не предоставляет их.

Вы можете создавать свои собственные, используя индексы (или представления по индексам):

scala> val a = Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)

scala> a.indices.view.filter(i=>a(i)%2==0).foreach(i=>a(i)=0)

scala> a
res1: Array[Int] = Array(1, 0, 3, 0, 5)

Это немного неловко, но обычно немного лучше, чем версия оператора if (в этом, по крайней мере, вы можете увидеть шаги фильтра и назначения отдельно).

2 голосов
/ 04 октября 2011

Вы можете предоставить свой фильтр и функцию сопоставления для функции объединения; Я пробовал пример на http://jsfiddle.net/xtofl/UDbyL/.

Идея состоит в том, чтобы применить «отображение» (которое я бы назвал отображение на месте ) ко всем элементам, соответствующим предикату фильтрации в исходном массиве .

2 голосов
/ 04 октября 2011

Является ли collect тем, что вы ищете?

scala> List(2, 3, 5, 6, 9).filter(_ < 5).map(_ * 100)
res30: List[Int] = List(200, 300)

scala> List(2, 3, 5, 6, 9).collect { case i if i < 5 => i * 100 }
res31: List[Int] = List(200, 300)
1 голос
/ 05 октября 2011

Проблема, с которой вы столкнулись, заключается в том, что вы думаете о фильтрации, а фильтрация - это , а не , что вы хотите. Если вы не хотите удалять элементы, это не фильтр.

Все, что вам нужно, это простая карта:

array.map(x => if(x > 10) x * 10 else x)

Или, если вы считаете, что ваши условия слишком сложны,

array.map {
    case x if x > 10 => x * 10
    case x => x
}
1 голос
/ 04 октября 2011

Hej jiaweihli

самое простое решение - переназначить его на ссылку ... то есть поменять ссылку, а не данные.Это имеет некоторые преимущества, если ссылка находится в других местах, где вы не поменяете ее под этими носами.

EX:

x = x.filter(filterOpp);

ps!второй пример там доцент работы.GL

0 голосов
/ 04 октября 2011

Как насчет этого: (psuedo javascript)

  filteredMap = function(element) {
    if(filterFunc(element)){
      return mapFunc(element);
    }
    return element;
  }


  array = array.map(filteredMap)

Если вы явно не обязаны изменять массив (который не является "функциональным"), это должно дать вам то, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...