简体   繁体   中英

How to apply filter on list of _2 of tuples in Scala?

I want all the lists(the first element of below tuple) if second element is the powers of 2. I am new to Scala and stuck with syntax. Could anyone help me here I want to apply filter on below code to get below output.

Output:

List(1,3)
List(1,7)
List(3,5)
List(7,9)

input:

scala> a.toList.combinations(2).map(x => (x, x.sum)).foreach(println)
(List(1, 3),4)
(List(1, 5),6)
(List(1, 7),8)
(List(1, 9),10)
(List(3, 5),8)
(List(3, 7),10)
(List(3, 9),12)
(List(5, 7),12)
(List(5, 9),14)
(List(7, 9),16)
val tups = List((List(1, 3),4), (List(1, 5),6), (List(1, 7),8) , 
                (List(1, 9),10), (List(3, 5),8), (List(3, 7),10), 
                (List(3, 9),12), (List(5, 7),12),
                (List(5, 9),14), (List(7, 9),16))

Using fold :

tups.foldLeft(List[List[Int]]())((a, b) => if((b._2 & (b._2 - 1)) == 0) a :+ b._1 else a)

Using filter and map :

tups.filter(e => (e._2 & (e._2 - 1)) == 0).map(_._1)

x & (x - 1) == 0 is the bitwise operation that checks if a number is a power of 2

For a more detailed explanation of the syntax, documentation for fold and other List operations can be found here

For

val xs = List(1,3,5,7,9)

another approach that incorporates the generation of input and corresponding filtering includes

import scala.math.log

// testPower true if log is integral value
// log_base n = log_e n / log_e base

def testPower(n: Int, base: Int = 2): Boolean = {
  val lg = log(n) / log(base)
  lg.toInt == lg 
}

xs.combinations(2).filter(ys => testPower(ys.sum)).toList

The test provided in @sinanspd answer is more succinct as well as more efficient; the test here generalises to any power in addition to 2. This solution works for any combination size as it sums up the entire combination (sub)list.

You can use the fact that the binary representation of an element that is the power of 2, has only 1 bit which is 1, and all. others are 0's. Then use toBinaryString method:

val xs = List(1, 3, 5, 7, 9).combinations(2).map(x => (x, x.sum)).toList
val result = xs.filter(_._2.toBinaryString.count(_ == '1') == 1).map(_._1)

Code run at Scastie .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM