How to flatten a nested list in Vim script? - list

I found some Vim list functions can not work as I thought.
For example:
let list0 = [1, [1, 2]]
echo count(list0, 1)
It returns 1, but I want it returns 2. So I think those functions can not deep into nested lists, only work on first level.
I think here I should expand nested list into a normal list like this:
list0 = [1, 1, 2]
How to flatten a nested list?

" Code from bairui##vim.freenode
" https://gist.github.com/3322468
function! Flatten(list)
let val = []
for elem in a:list
if type(elem) == type([])
call extend(val, Flatten(elem))
else
call add(val, elem)
endif
unlet elem
endfor
return val
endfunction
Here unlet elem is necessary. Because the elem variable is changing, it is a list item, or a list, and VimL does not support assign a list item to a list, and vice versa.

You can use reduce() since 8.2.0878:
let mylist = [[1, 2], [3, 4], 5]
echo reduce(mylist, { acc, val -> type(val) == 3 ? extend(acc, val) : add(acc, val)})
outputs:
[1, 2, 3, 4, 5]

I suggest vital.vim's Data.List.flatten as an another answer ;D
https://github.com/vim-jp/vital.vim

Related

How can i sort a list from specifik criteria

I have this list and I want to sort the list. This is just a smaller example of what I want to do, but I get the same error. I dont understand why I can't make this work.
I have tried using google to solve the problem but without luck.
lst = [3, 4, 5, 6]
if lst < 4:
lst.pop()
print(lst)
How can i do this it shows
TypeError:'<' not supported between instances of 'list' and 'in
I think that your goal is to remove all elements in the list that are lesser than 4. You can use this simple list comprehension in order to achieve what you want:
lst = [3, 4, 5, 6]
lst = [elem for elem in lst if elem >= 4]
print(lst)
Output:
[4, 5, 6]

Kotlin prepend element

I am searching for Kotlin alternative to:
(cons 1 '(2 3)) in lisp or
1 : [2, 3] in haskell or
1 :: List(2, 3) in scala,
(which all result in sth like [1, 2, 3])
so I can prepend an element to a List<T> (or any other list you can offer).
It will also be fine if one could provide O(1) head and tail Kotlin alternatives (I've found just first())
I think the easiest would be to write:
var list = listOf(2,3)
println(list) // [2, 3]
list = listOf(1) + list
println(list) // [1, 2, 3]
There is no specific tail implementation, but you can call .drop(1) to get the same. You can make this head\tail more generic by writing these extension properties:
val <T> List<T>.tail: List<T>
get() = drop(1)
val <T> List<T>.head: T
get() = first()
Then:
val list = listOf(1, 2, 3)
val head = list.head
val tail = list.tail
Some more info: Kotlin List tail function
Any class which implements Deque will suitable for you, for example LinkedList:
val linkedList = LinkedList(listOf(2, 3))
linkedList.push(1)
println(linkedList) // [1, 2, 3]
Creating lists throught constructor LinkedList(listOf(2, 3)) in many places can be annoying, so feel free to write factory method:
fun <T> linkedListOf(vararg elements: T): LinkedList<T> {
return LinkedList<T>(elements.toList())
}
// Usage:
val list = linkedListOf(2, 3)
list.push(1)
println(list) // [1, 2, 3]
Simple, just wrap the element to prepend in a List and then use the + operator (or List.plus()) to concatenate the two Lists:
val list1 = listOf(2, 3) // [2, 3]
val list2 = listOf(1) + list1 // [1, 2, 3]
For your second question, in Kotlin 1.2 there are:
List.first()
List.last()
Both are O(1)
This could be done easily with extension functions as below
Prepending element
fun <T> MutableList<T>.prepend(element: T) {
add(0, element)
}
Prepending list
fun <T> MutableList<T>.prependAll(elements: List<T>) {
addAll(0, elements)
}
Inserts an element into the list at the specified index.
abstract fun add(index: Int, element: E)
Thus answer is
list.add(0,element)
If you do that often in your code for some reason, consider adding an extension operator method such as:
operator fun <T> T.plus(tail: List<T>): List<T> {
val list = ArrayList<T>(1 + tail.size)
list.add(this)
list.addAll(tail)
return list
}
Then your code could work Scala-like: 1 + listOf(2, 3)
Another way to achieve the same behaviour, shorter but sacrifices some memory:
operator fun <T> T.plus(tail: List<T>): List<T> {
return mutableListOf(this).apply {
addAll(tail)
}
}
To be as close to Lisp as possible consider using immutable linked list.
You can use pcollections
val list = ConsPStack.from(listOf(2, 3))
val newList = list + 1
println(list) // [2, 3]
println(newList) // [1, 2, 3]
Head:
list.first() // 1
list[0] // 1
(unfortunately this thing needs one allocation)
Tail:
list - 0 // [2, 3]
list.subList(1) // [2, 3]
Looks rather ugly.
Hopefully we'll get better API when kotlinx.collections.immutable will be ready. It's an effort to create standard Kotlin immutable collections (not just read-only ones that we currently have). As of now this project is still at very early stage (I was unable to find structure that supports efficient prepend/head/tail there)
I'm not entirely sure what you want to do, so please try one of the following.
Mutating list:
val list = mutableListOf(3, 2)
list.add(1)
Copping an immutable list:
var list = listOf(3, 2)
list = list + 1

python3.2)append two element in a list(lists in a list)

If I have an input like this (1, 2, 3, 4, 5, 6)
The output has to be ... [[1, 2], [3, 4], [5, 6]].
I know how to deal with if it's one element but not two.
x=[]
for number in numbers:
x.append([number])
I'll appreciate your any help!
Something like this would work:
out = []
lst = (1,2,3,4,5,6,7,8,9,10)
for x in range(len(lst)):
if x % 2 == 0:
out.append([lst[x], lst[x+1]])
else:
continue
To use this, just set lst equal to whatever list of numbers you want. The final product is stored in out.
There is a shorter way of doing what you want:
result = []
L = (1,2,3,4,5,6,7,8,9,10)
result = [[L[i], L[i + 1]] for i in range(0, len(L) - 1, 2)]
print(result)
You can use something like this. This solution also works for list of odd length
def func(lst):
res = []
# Go through every 2nd value | 0, 2, 4, ...
for i in range(0, len(lst), 2):
# Append a slice of the list, + 2 to include the next value
res.append(lst[i : i + 2])
return res
# Output
>>> lst = [1, 2, 3, 4, 5, 6]
>>> func(lst)
[[1, 2], [3, 4], [5, 6]]
>>> lst2 = [1, 2, 3, 4, 5, 6, 7]
>>> func(lst2)
[[1, 2], [3, 4], [5, 6], [7]]
List comprehension solution
def func(lst):
return [lst[i:i+2] for i in range(0, len(lst), 2)]
Slicing is better in this case as you don't have to account for IndexError allowing it to work for odd length as well.
If you want you can also add another parameter to let you specify the desired number of inner elements.
def func(lst, size = 2): # default of 2 it none specified
return [lst[i:i+size] for i in range(0, len(lst), size)]
There's a few hurdles in this problem. You want to iterate through the list without going past the end of the list and you need to deal with the case that list has an odd length. Here's one solution that works:
def foo(lst):
result = [[x,y] for [x,y] in zip(lst[0::2], lst[1::2])]
return result
In case this seems convoluted, let's break the code down.
Index slicing:
lst[0::2] iterates through lst by starting at the 0th element and proceeds in increments of 2. Similarly lst[1::2] iterates through starting at the 1st element (colloquially the second element) and continues in increments of 2.
Example:
>>> lst = (1,2,3,4,5,6,7)
>>> print(lst[0::2])
(1,3,5,7)
>>> print(lst[1::2])
(2,4,6)
zip: zip() takes two lists (or any iterable object for that matter) and returns a list containing tuples. Example:
>>> lst1 = (10,20,30, 40)
>>> lst2 = (15,25,35)
>>> prit(zip(lst1, lst2))
[(10,15), (20,25), (30,35)]
Notice that zip(lst1, lst2) has the nice property that if one of it's arguments is longer than the other, zip() stops zipping whenever the shortest iterable is out of items.
List comprehension: python allows iteration quite generally. Consider the statement:
>>> [[x,y] for [x,y] in zip(lst1,lst2)]
The interior bit "for [x,y] in zip(lst1,lst2)" says "iterate through all pairs of values in zip, and give their values to x and y". In the rest of the statement
"[[x,y] for [x,y] ...]", it says "for each set of values x and y takes on, make a list [x,y] to be stored in a larger list". Once this statement executes, you have a list of lists, where the interior lists are all possible pairs for zip(lst1,lst2)
Very Clear solution:
l = (1, 2, 3, 4, 5, 6)
l = iter(l)
w = []
for i in l:
sub = []
sub.append(i)
sub.append(next(l))
w.append(sub)
print w

How do I add elements of a "zipped" list

I have a list and I want to add each of the pairs in the list
For example:
mylist = [(0,5), (4,5), (2,3)]
I want to get
newlist = [5, 9, 5]
Whatever language this is you could use a map. In python it would look like:
map(lambda x: x[0] + x[1], my_list)
Or even simpler:
map(sum, my_list)
Both returning:
[5, 9, 5]

How do you merge indexes of two lists in Groovy?

I have two lists that I need to merge into a new list, but the new list needs to contain merged indexes of the original lists. For example:
List1 = [1, 2, 3]
List2 = [a, b, c]
I need the output to be:
finalList = [1a, 2b, 3c]
I need to be able to do this in groovy. I appreciate any help you can provide.
Assuming both lists are the same size, in Groovy 2.4+,
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
assert ['1a', '2b', '3c'] == list1.withIndex().collect { it, index -> it + list2[index] }
Alternatively and a bit more simply in Groovy 1.5+,
assert ['1a', '2b', '3c'] == [list1, list2].transpose()*.sum()
The following is very close to doelleri's solution:
In Groovy 2.4+
println ([list1, list2].transpose().collect{it -> it[0] + it[1]})
OUTPUT
[1a, 2b, 3c]