Example:
let list = [['aen', '2'], ['ben', '3'], ['Aen', '4'], ['Ben', '5']]
sort(list, 1)
Output:
let list = [['aen', '2'], ['Aen', '4'], ['ben', '3'], ['Ben', '5']]
Expected output:
let list = [['Aen', '4'], ['aen', '2'], ['Ben', '5'], ['ben', '3']]
In python that would be easy to do but it seems not te be possible to use the python sorted() command with a vim list.
How can I sort the list as expected?
UPDATE:
Maybe a solution would be:
for i in range(0,len(list)-1)
let #b= join(list[i], "|||")
endfor
This would put all the lines in a register but how can I sort the lines in a register?
EDIT:
Found a solution with the help of python (within Vim Function)
python3 << endpython
import vim
list2 = vim.eval('list')
list3 = sorted(list2, key=lambda v: (v[0].upper(), v[0].islower()))
vim.command("let list= %s"% list3)
endpython
echo list --> [['Aen', '4'], ['aen', '2'], ['Ben', '5'], ['ben', '3']]
Reman: Found a solution with the help of python (within Vim Function)
python3 << endpython
import vim
list2 = vim.eval('list')
list3 = sorted(list2, key=lambda v: (v[0].upper(), v[0].islower()))
vim.command("let list= %s"% list3)
endpython
echo list --> [['Aen', '4'], ['aen', '2'], ['Ben', '5'], ['ben', '3']]
sort() takes an optional parameter which is a function. Define your function that return -1, 0, or 1 depending on the first element of your sub-lists.
Note that you'll have to define the function for your altered lexical order.
May be instead, you could sort the transposed versions with tr(), and then transpose back after the sort.
I think to obtain your expected result in python, you have to write your own compare function too. In vim, you can first impl. the compare function, and pass the function ref to the sort() function.
Please check the :h sort( for detail
Related
Please suggest the regex for following dataset
gSoCa,['25','78'],fa,GT,GTM_19,gPfRec,['22','78','78'],10,fa,GT,TS/C_LE_RE,
gPreRe,['12'],10,fa,GT,TS/C_L_OW,gTLAsTe,['2'],PT,TEST/UP_P_IST,gBeAdRe,['78','2'],5,fa,GET,ulr/UTC_9,gEdiRen,['2'],fa,GT,ua/ngs_2018-Copy,
tried:
(\w+,(\['?\d+'?(?:,\s*'?\d+'?)*\]),(\w+),([\w/_-]+|[\w/]+),([\w/_-]+|[\w/]+)),
expected is python tuple:
[gSoCa,25,78,fa,GT,GTM_19,.....ua/ngs_2018-Copy]
see the demo
https://regex101.com/r/zHXUmh/1
Maybe something like this could work:
text = """gSoCa,['25','78'],fa,GT,GTM_19,
gPfRec,['22','78','78'],10,fa,GT,TS/C_LE_RE,
gPreRe,['12'],10,fa,GT,TS/C_L_OW,
gTLAsTe,['2'],PT,TEST/UP_P_IST,
gBeAdRe,['78','2'],5,fa,GET,ulr/UTC_9,
gEdiRen,['2'],fa,GT,ua/ngs_2018-Copy,"""
result = [s.strip("[]'\n") for s in text.split(",")]
print(result)
Your "expected" tuple is impossible in Python as it contains strings without quotes. That said, all it needs is a series of not-in-set characters:
print (tuple(re.findall(r"[^\[\],']+", text)))
result (as noted, not exactly what you want!):
('gSoCa', '25', '78', 'fa', 'GT', 'GTM_19', 'gPfRec', '22', '78', '78', '10', 'fa', 'GT', 'TS/C_LE_RE')
I have two lists that I zip() together:
>> x1 = ['1', '2', '3']
>> y1 = ['a', 'b', 'c']
>> zipped = zip(x1, y1)
As expected so far:
>> print(list(zipped)
[('1', 'a'), ('2', 'b'), ('3', 'c')]
From the docs, it seems like I can just do this to get back the two lists from the zip object:
>> x2, y2 = zip(*zipped)
But instead I get the error:
Traceback (most recent call last):
File "/usr/lib/python3.5/site-packages/IPython/core/interactiveshell.py", line 2869, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-6-58fe68d00d1c>", line 1, in <module>
x2, y2 = zip(*zipped)
ValueError: not enough values to unpack (expected 2, got 0)
Obviously I'm not understanding something simple about the zip object.
Edit:
As #daragua points out below, the print(list(zipped)) was actually consuming the zipped object, thus making it empty. That's true, for my simple example. I'm still having an issue with my real code.
What I'm trying to to is write a unit test for Django view that has a zipped object in it's context. The view works fine, I'm just struggling writing the test for it.
In my view context I have this:
for season in context['pools']:
commissioner.append(season.pool.is_commish(self.request.user))
context['pools'] = zip(context['pools'], commissioner)
This works as expected. The pools context object is two lists, which the template handles just fine:
{% for season, commissioner in pools %}
The test I'm struggling to write is to check if the commissioner value is correct for a the pool object for the logged in user. In my test:
context = self.response.context['pools']
print(list(context ))
In this case, context is an empty list [].
The zip function returns an iterator. The print(list(zipped)) call thus runs the iterator til its end and the next zip(*zipped) doesn't have anything to eat.
Just zip back to reverse:
>>> zipped=zip(x1, y1)
>>> x2, y2=zip(*zipped)
>>> x2
('1', '2', '3')
And use map if you want the result to be a list rather than a tuple:
>>> zipped=zip(x1, y1)
>>> x2, y2=map(list, zip(*zipped))
>>> x2
['1', '2', '3']
>>> y2
['a', 'b', 'c']
Side note: In Python 3, zip returns a one-time use iterator. That is why zip needs to be called again after each use (in Python 3 only)
Ultimately the issue wasn't with the zip object at all.
If you are sending a zip object to a Django context:
x = ['1', '2', '3']
y = ['a', 'b', 'c']
context['zipped'] = zip(x, y)
And if you are trying to write a unit test for the context data, you don't need to unzip, as it can be pulled from the response context already unzipped:
def test_zipped_data(TestCase):
x, y = self.response.context_data['zipped']
self.assertIn('b', y)
However if your context data is empty (zipped == []), then you will get the ValueError exception. But that's just because your context is empty and your test worked!
I am trying to sort a list of 100 filenames so they will used in the right order in later calculations. All the filenames have 'name_1' in the beginning of the name and '_out.txt' at the end. The difference is a number in between, going from 1-100
The list looks a bit like this:
['name_1_100_out.txt', 'name_1_10_out.txt', 'name_1_6_out.txt', 'name_1_5_out.txt', 'name_1_2_out.txt']
For this actual example I want:
['name_1_2_out.txt', 'name_1_5_out.txt', 'name_1_6_out.txt', 'name_1_10_out.txt', 'name_1_100_out.txt']
Now I have tried both list.sort and sorted(list) but with no luck. I have also tried with the key=int or key=str but none of them could help, since it seems, that it could not convert only a part of the string to int.
Can anyone help me with advice
You need leading zeros to sort the way you want.
#!/usr/bin/python
# -*- coding: utf-8 -*-
L=['name_1_100_out.txt', 'name_1_10_out.txt', 'name_1_6_out.txt', 'name_1_5_out.txt', 'name_1_2_out.txt']
OUT=[]
n='100' # max number
for item in L:
old=item[7:-8] # Faulty index
if len(old) < len(n):
new='0'*(len(n)-len(old))+old # Nice index
item=item.replace(old, new)
OUT.append(item)
OUT.sort()
print OUT
Result
['name_1_002_out.txt', 'name_1_005_out.txt', 'name_1_006_out.txt', 'name_1_010_out.txt', 'name_1_100_out.txt']
I would suggest renaming files to make life easier later on since not all file managers display faulty filenames in order.
You can use the key function for this task:
>>> l = ['name_1_100_out.txt', 'name_1_10_out.txt', 'name_1_6_out.txt', 'name_1_5_out.txt', 'name_1_2_out.txt']
>>> sorted(l,key=lambda s: int(s.split('_')[2]))
['name_1_2_out.txt', 'name_1_5_out.txt', 'name_1_6_out.txt', 'name_1_10_out.txt', 'name_1_100_out.txt']
lista = ['2','3','5','8','4','6','1']
listb = [('2','3'),('5','8'),('4','6'),('1','9')]
listc = {'a':'3','b':'5','c':'9','d':'4','e':'2','f':'0'}
d = sorted(lista, key=lambda item:int(item), reverse=True)
e = sorted(listb, key=lambda item:int(item[0]) + int(item[1]), reverse=True)
f = sorted(listc.items(), key=lambda item:int(item[1]), reverse=True)
print(d)
print(e)
print(f)
output:
['8', '6', '5', '4', '3', '2', '1']
[('5', '8'), ('4', '6'), ('1', '9'), ('2', '3')]
[('c', '9'), ('b', '5'), ('d', '4'), ('a', '3'), ('e', '2'), ('f', '0')]
I know that this is probably a silly question and I apologize for that, but I am very new to python and have tried to solve this for a long time now, with no success.
I have a list of tuples similar to the one bellow:
data = [('ralph picked', ['nose', '4', 'apple', '30', 'winner', '3']),
('aaron popped', ['soda', '1', 'popcorn', '6', 'pill', '4', 'question', '29'])]
I would like to sort the nested list in descending other:
data = [('ralph picked', ['apple', '30', 'nose', '4', 'winner', '3']),
('aaron popped', ['question', '29', 'popcorn', '6', 'pill', '4', 'soda', '1'])]
I tried using simple
sorted(data)
but what I get is only the first item of tuple sorted. What I am missing here? I really thank you for any help.
Let's consider only the inner list. The first issue is that it seems like you want to keep word, number pairs together. We can use zip to combine them, remembering that seq[::2] gives us every second element starting at the 0th, and seq[1::2] gives us every second starting at the first:
>>> s = ['nose', '4', 'apple', '30', 'winner', '3']
>>> zip(s[::2], s[1::2])
<zip object at 0xb5e996ac>
>>> list(zip(s[::2], s[1::2]))
[('nose', '4'), ('apple', '30'), ('winner', '3')]
Now, as you've discovered, if you call sorted on a sequence, it sorts first by the first element, then by the second to break ties, etc., going as deep as it needs to. So if we call sorted on this:
>>> sorted(zip(s[::2], s[1::2]))
[('apple', '30'), ('nose', '4'), ('winner', '3')]
Well, that looks like it works, but only by fluke because apple-nose-winner is in alphabetical order. Really we want to sort by the second term. sorted takes a key parameter:
>>> sorted(zip(s[::2], s[1::2]), key=lambda x: x[1])
[('winner', '3'), ('apple', '30'), ('nose', '4')]
That didn't work either, because it's sorting the number strings lexicographically (dictionary-style, so '30' comes before '4'). We can tell it we want to use the numerical value, though:
>>> sorted(zip(s[::2], s[1::2]), key=lambda x: int(x[1]))
[('winner', '3'), ('nose', '4'), ('apple', '30')]
Almost there -- we want this reversed:
>>> sorted(zip(s[::2], s[1::2]), key=lambda x: int(x[1]), reverse=True)
[('apple', '30'), ('nose', '4'), ('winner', '3')]
And this is almost right, but we need to flatten it. We can use either a nested list comprehension:
>>> s2 = sorted(zip(s[::2], s[1::2]), key=lambda x: int(x[1]), reverse=True)
>>> [value for pair in s2 for value in pair]
['apple', '30', 'nose', '4', 'winner', '3']
or use itertools.chain:
>>> from itertools import chain
>>> list(chain.from_iterable(s2))
['apple', '30', 'nose', '4', 'winner', '3']
And I think that's where we wanted to go.
This is what my text file consists of:
"I like ice cream very much"
So far this is my code:
f = open('nums.txt', 'r')
list = []
data1 = readline()
print (data1)
This is the output:
I like ice cream very much
I was wondering how I could get it so each word is separated e.g. ['I', 'like', 'ice', 'cream', 'very', 'much']
I am working in Python 3.3. Any ideas?
Use the str.split method:
print(data1.split())
>>> data1 = 'I like ice cream very much'
>>> data1.split()
['I', 'like', 'ice', 'cream', 'very', 'much']
Here is the corresponding one-liner:
print(open("nums.txt").read().split())