Apologies if this is obvious but I'm pretty new to Python and I cannot get my head around this problem. In the following code I have populated a tuple with a series of lists and I am trying to create a new list with items from this tuple. I was hoping that the final result will be that test_raw remains unchanged and test_working will look like the following:
[['aa', 1, 2, 99.5, ['bb', 1, 2, 27.2]],
['aa', 5, 5, 74.2, ['bb', 5, 5, 37]]]
However, in the process, I seem to be appending the 'bb' lists to my tuple as well. I thought that once a tuple is constructed, it cannot be changed but obviously not. Any idea what is happening?
test_raw = (['aa',1,2,99.5],
['bb',1,2,27.2],
['aa',5,5,74.2],
['bb',5,5,37])
test_working = []
for i in range(len(test_raw)):
if test_raw[i][0] == "aa":
test_working.append(test_raw[i])
for i in range(len(test_raw)):
if test_raw[i][0] == "bb":
for j in range(len(test_working)):
if test_working[j][1:3] == test_raw[i][1:3]:
test_working[j].append(test_raw[i])
break
print(test_raw)
(['aa', 1, 2, 99.5, ['bb', 1, 2, 27.2]], ['bb', 1, 2, 27.2], ['aa',.....)
You are not appending to the tuple itself, but the lists inside tuple. I won't debug your code for you but when you run your code, you'll notice that your first list (originally ['aa',1,2,99.5]) has a new element in it (['bb', 1, 2, 27.2])
You aren't appending to the tuple, you are just changing the lists that are inside that tuple
Consider this simple example
my_tuple = (1,2,3, [4,5,6])
my_tuple[3].append(7)
This doesn't add onto my_tuple, just the list that is the last element of it
Related
I am trying to extract particular lines from txt output file. The lines I am interested in are few lines above and few below the key_string that I am using to search through the results. The key string is the same for each results.
fi = open('Inputfile.txt')
fo = open('Outputfile.txt', 'a')
lines = fi.readlines()
filtered_list=[]
for item in lines:
if item.startswith("key string"):
filtered_list.append(lines[lines.index(item)-2])
filtered_list.append(lines[lines.index(item)+6])
filtered_list.append(lines[lines.index(item)+10])
filtered_list.append(lines[lines.index(item)+11])
fo.writelines(filtered_list)
fi.close()
fo.close()
The output file contains the right lines for the first record, but multiplied for every record available. How can I update the indexing so it can read every individual record? I've tried to find the solution but as a novice programmer I was struggling to use enumerate() function or collections package.
First of all, it would probably help if you said what exactly goes wrong with your code (a stack trace, it doesn't work at all, etc). Anyway, here's some thoughts. You can try to divide your problem into subproblems to make it easier to work with. In this case, let's separate finding the relevant lines from collecting them.
First, let's find the indexes of all the relevant lines.
key = "key string"
relevant = []
for i, item in enumerate(lines):
if item.startswith(key):
relevant.append(item)
enumerate is actually quite simple. It takes a list, and returns a sequence of (index, item) pairs. So, enumerate(['a', 'b', 'c']) returns [(0, 'a'), (1, 'b'), (2, 'c')].
What I had written above can be achieved with a list comprehension:
relevant = [i for (i, item) in enumerate(lines) if item.startswith(key)]
So, we have the indexes of the relevant lines. Now, let's collected them. You are interested in the line 2 lines before it and 6 and 10 and 11 lines after it. If your first lines contains the key, then you have a problem – you don't really want lines[-1] – that's the last item! Also, you need to handle the situation in which your offset would take you past the end of the list: otherwise Python will raise an IndexError.
out = []
for r in relevant:
for offset in -2, 6, 10, 11:
index = r + offset
if 0 < index < len(lines):
out.append(lines[index])
You could also catch the IndexError, but that won't save us much typing, as we have to handle negative indexes anyway.
The whole program would look like this:
key = "key string"
with open('Inputfile.txt') as fi:
lines = fi.readlines()
relevant = [i for (i, item) in enumerate(lines) if item.startswith(key)]
out = []
for r in relevant:
for offset in -2, 6, 10, 11:
index = r + offset
if 0 < index < len(lines):
out.append(lines[index])
with open('Outputfile.txt', 'a') as fi:
fi.writelines(out)
To get rid of duplicates you can cast list to set; example:
x=['a','b','a']
y=set(x)
print(y)
will result in:
['a','b']
When i execute this testing code below, i get the error below it:
my_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
my_input = input("Pick a number from 1 to 10?")
number_index = my_numbers.index(my_input)
print(number_index)
ERROR-----
number_index = my_numbers.index(my_input) ValueError: '1' is not in
list
is this python? if so, look like is python 3, then the error is simple: input give you a string, and you have a list of integers and no integer is going to be equal to a string, ever, so when you pass my_input, a string, to index it search in the list my_numbers for a match but all the things inside it are integer so it fail and give the error. The solution is simple transform the input to a integer like this:
my_input = int( input("Pick a number from 1 to 10?") )
the same apply to other languages but the fine details may vary...
I am writing a program that outputs a list of ordered lists of numbers. Say the output is as follows:
[1,1,1];
[1,1,2]
I would like to look at the output by eye and make some sense of it, but my output is hundreds to thousands of lines long. I would like to write the output in the following more compact format: [1,1,1/2], where the slash indicates that in the third slot I can have a 1 or a 2. So, for a longer example, [1/2, 1/3, 5, 8/9] would be the compact way of writing [1,1,5,8];[1,1,5,9];[1,3,5,8]; etc. Can anyone suggest a pseudocode algorithm for accomplishing this?
Edit: All of the lists are the same length. Also, I expect in general to have multiple lists at the end. For example {[1,1,2], [1,1,3], [1,2,4]} should become {[1,1,2/3], [1,2,4]}.
What'd I do is use a hash at each element in the first list. You'd then iterate through the remaining lists, and for each position in the other lists, you'd check against the hash in the first / original list for that index to see if you'd seen it before. So you'd end up with something like:
[1 : {1}, 1: {1, 3}, 5: {5}, 8: {8, 9}]
And then when printing / formatting the list, you'd just print each key in the hash, except you'd use slashes or whatever.
EDIT: Bad Psuedocode (python)(untested):
def shorten_list(list_of_lists):
primary_list = list_of_lists[0]
hash_values = [{} * len(primary_list)]
for i in range(len(list_of_lists)):
current_list = list_of_lists[i]
for j in range(current_list):
num = current_list[j]
if num not in hash_values[j]:
hash_values[j] = j
for i in range(len(hash_values)):
current_dict = hash_values[i]
print primary_list[i]
for key in current_dict:
if key != primary_list[i]:
print '/', key
Here's actual code to sort the lists the way you wanted. But maybe the most useful visualization would be a scatter plot. Import the data into your favorite spreadsheet, and plot away.
$(document).ready( function(){
var numbers = [
[1, 1, 5, 8],
[1, 1, 5, 9],
[1, 3, 5],
[1, 1, 5, 10, 15]];
$('#output').text(JSON.stringify(compactNumbers(numbers)));
});
function compactNumbers(numberlists){
var output = [];
for(var i = 0; i < numberlists.length; i++){
for(var j = 0; j < numberlists[i].length; j++) {
if(!output[j]) output[j] = [];
if($.inArray(numberlists[i][j], output[j]) == -1){
output[j].push(numberlists[i][j]);
}
}
}
return(output);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
i have a scala list of tuples,
val stdLis:List[(String,Int)]=null
I need to combine the consecutive integers in the list to form ranges. The final result only needs ranges of integers from the list. The following approach leaves the non-consecutive numbers. But i need to form ranges for the consecutive numbers and also retain non consecutive numbers in the final list.
def mergeConsecutiveNum(lis:List[(String,Int)])={
var lisBuf = new ListBuffer[(String,Int)]
val newRanges = new ListBuffer[(Int,Int)]()
if(lis.size>1)
lis.sliding(2).foreach{i=>
if(i(0)._2+1 == i(1)._2)
lisBuf.appendAll(i)
else{
//println(lisBuf)
if(lisBuf.size>1) {
newRanges.append((lisBuf.head._2, lisBuf.last._2))
newRanges.append((i(0)._2,i(1)._2))
}
lisBuf.clear()
}
}else
newRanges.append((lis.head._2,0))
newRanges
}
for example:
val lis = List(("a",1),("b",2),("c",3),("d",4),("e",6),("f",7),("g",9))
it should give
lis((1,4),(6,7),(9,0))
Don't exactly know what you are asking.
Your code does not return anything.
Anyways, assuming that you need to merge two consecutive numbers in the list and create a range of list based on those numbers, here is something you can try
List(("", 5),("", 10),("", 6),("", 10)).map(_._2).grouped(2).map(ele => ele(0) to ele(1)).toList
List(Range(5, 6, 7, 8, 9, 10), Range(6, 7, 8, 9, 10))
Does Groovy have a smart way to check if a list is sorted? Precondition is that Groovy actually knows how to sort the objects, e.g. a list of strings.
The way I do right now (with just some test values for this example) is to copy the list to a new list, then sort it and check that they are equal. Something like:
def possiblySorted = ["1", "2", "3"]
def sortedCopy = new ArrayList<>(possiblySorted)
sortedCopy.sort()
I use this in unit tests in several places so it would be nice with something like:
def possiblySorted = ["1", "2", "3"]
possiblySorted.isSorted()
Is there a good way like this to check if a list is sorted in Groovy, or which is the preffered way? I would almost expect Groovy to have something like this, since it is so smart with collections and iteration.
If you want to avoid doing an O(n*log(n)) operation to check if a list is sorted, you can iterate it just once and check if every item is less or equals than the next one:
def isSorted(list) {
list.size() < 2 || (1..<list.size()).every { list[it - 1] <= list[it] }
}
assert isSorted([])
assert isSorted([1])
assert isSorted([1, 2, 2, 3])
assert !isSorted([1, 2, 3, 2])
Why not just compare it to a sorted instance of the same list?
def possiblySorted = [ 4, 2, 1 ]
// Should fail
assert possiblySorted == possiblySorted.sort( false )
We pass false to the sort method, so it returns a new list rather than modifying the existing one
You could add a method like so:
List.metaClass.isSorted = { -> delegate == delegate.sort( false ) }
Then, you can do:
assert [ 1, 2, 3 ].isSorted()
assert ![ 1, 3, 2 ].isSorted()