How to sort list by another list? - excel

I have excel list of names(Datalist) and I need to sort it to be in exact same order as similar list(Patternlist).
How can i sort Datalist to have same order as Patternlist?
Patternlist(each letter is first cell in a row):
X
Y
Z
Q
Datalist(each letter is first cell in a row):
Q
X
Y
Z

Manually doing it :
Label each row in Patternlist with 1,2,3,..
use index match to generate a 'sequence' list from the Datalist
=index([Datalist_QXYZ],match([1st_named_cell],[Patternlist_XYZQ],0))
copy the generated sequence list and paste as values, then sort.
(3b) If you need to actively generate new list.. then use rank() to manually sort it.
Hope it helps..

Related

Textjoin values of column B if duplicates are present in column A

I want to consolidate the data of column B into a single cell ONLY IF the index (ie., Column A) is duplicated.
For example:
Currently, I'm doing manually for each duplicated index by using the following formula:
=TEXTJOIN(", ",TRUE,B4:B6)
Is there a better way to do this all at once?
Any help is appreciated.
There may easier way but you can try this formula-
=BYROW(A2:A17,LAMBDA(p,IF(INDEX(MAP(A2:A17,LAMBDA(x,SUM(--(A2:INDEX(A2:A17,ROW(x)-1)=x)))),ROW(p)-1,1)=1,TEXTJOIN(", ",1,FILTER(B2:B17,A2:A17=p)),"")))
Using REDUCE might be possible for a more succinct solution, though try this for now:
=BYROW(A2:A17,LAMBDA(ζ,LET(α,A2:A17,IF((COUNTIF(α,ζ)>1)*(COUNTIF(INDEX(α,1):ζ,ζ)=1),TEXTJOIN(", ",,FILTER(B2:B17,α=ζ)),""))))
For the sake of alternatives about how to solve it:
Using XMATCH/UNIQUE
=LET(A, A2:A17, ux, UNIQUE(A),idx, FILTER(XMATCH(ux, A), COUNTIF(A, ux)>1),
MAP(SEQUENCE(ROWS(A)), LAMBDA(s, IF(ISNA(XMATCH(s, idx)), "", TEXTJOIN(",",,
FILTER(B2:B17, A=INDEX(A,s)))))))
or using SMALL/INDEX to identify the first element of the repetition:
=LET(A, A2:A17, n, ROWS(A), s, SEQUENCE(n),
MAP(A, s, LAMBDA(aa,ss, LET(f, FILTER(B2:B17, A=aa), IF((ROWS(f)>1)
* (INDEX(s, SMALL(IF(A=aa, s, n+1),1))=ss), TEXTJOIN(",",, f), "")))))
Here is the output:
Explanation
XMATCH and UNIQUE
The main idea here is to identify the first unique elements of column A via ux, and find their corresponding index position in A via XMATCH(ux, A). It is an array of the same size as ux. Then COUNTIF(A, ux)>1) returns an array of the same size as XMATCH output indicating where we have a repetition.
Here is the intermediate result:
XMATCH(ux, A) COUNTIF(A, ux)>1)
1 FALSE
2 FALSE
3 TRUE
6 FALSE
7 TRUE
9 TRUE
11 FALSE
12 TRUE
15 FALSE
16 FALSE
so FILTER takes only the rows form the first column where the second column is TRUE, i.e the index position (idx) where the repetition starts. For our sample it will be: {3;7;9;12}.
Now we iterate over the sequence of index positions (s) via MAP . If s is found in idx via XMATCH (also XLOOKUP(s, idx, TRUE, FALSE) can be used for the same purpose) then we join the values of column B filtered by column A equal to INDEX(A,s).
SMALL and INDEX
This is a more flexible approach because in the case we want to do the concatenation in another position of the repetition you just need to specify the order and the formula doesn't change.
We iterate via MAP through elements of column A and index position (s). The name f has the filtered values from column B where column A is equal to a given value of the iteration aa. We need to identify only filtered rows with repetition, so the first condition ROWS(f) > 1 ensures it.
The second condition identifies only the first element of the repetition:
INDEX(s, SMALL(IF(A=aa, s, n+1),1))=ss
The second argument of SMALL indicates we want the first smallest value, but it could be the second, third, etc.
Where A is equal to aa, IF assigns the corresponding value of the sequence (remember IF works as an array formula), if not then it assigns a value that will never be the smallest one, for example, n+1, where n represents the number of rows of column B. SMALL returns the smallest index position. If the current index position ss is not the smallest one, the conditions FALSE.
Finally, we do a TEXTJOIN only when both conditions are met (we multiply them to ensure an AND condition).

Excel Formula LET function based on Criteria

Self-Learning Excel, Im new with the LET function and i am Looking for a fix to the below formula, where B5144 is user input for Date in which the LET function will create a table based on user input in B5144 (Filter records where date values are matching with B5144).
Either using an IF/ Filter function as validation before generating a result. Where only records in the table that match the date value in B5144 will be displayed.
=SORT((LET(x,UNIQUE(D2:D5140),y,SUMIFS(J2:J5140,D2:D5140,x),CHOOSE({1,2},x,y))))
If you are going to use a dynamic array (filter) you are going to have to start with the filter and work your way out:
FILTER(A2:J5140,A2:A5140=B5144)
Once you have this "sub array" it is the only thing you will use, you will make no further references to A:xxx or J:xxx.
LET(results,FILTER(A2:J5140,A2:A5140=B5144),
A, index(results,,1),
x, index(results,,4),
y, index(results,,10) )
And then move on from there.
results is a variable height x 10 column width array.
A, x, and Y are the same variable height x 1 column width array.
I believe your "unique" function is going to create a hot mess unless you are really clear in your logic. Array "x" will often be shorter in length than A and y, and this may or may not be what you want.
You may have to nest Filters: =Filter( Filter( xx by date ) by unique D )
In this way, you always end up with a matched A, x, and y array.
Hope this helps get you in the right direction. Let us know if you need more.
———-
Edit: I only recently came to overflow from stackexchange so I don’t have enough points to make comments yet, so I’ll respond here.
My formula above just does the filter and sets the definitions, are you then entering your desired formula at the end just inside the final parenthesis?

Use writerow to put a list of elements in the same row

Here is the source code I have. xs is a list of time float numbers, I am trying to put all of the elements of the list to the same row.
outFile=open('testing.csv','w',newline='')
writeFile=csv.writer(outFile)
writeFile.writerow(['cell'])
writeFile.writerow(['LevelLine for Impedance Magnitude:',baseline])
writeFile.writerow(['TimeMag (second):',xs])'
First I had tried using the for loop to load the numbers such as
for i in range(len(xs)-1):
writeFile.writerow('TimeMag(second):',xs[i])
However, the output result of this code prints xs[i] in different rows. I had tried watching the video and checked the CSV writerow function, but I couldn't find anything that put a list of elements to the same row.
I want my output like this:
output:
row 1: Cell
row 2: TimeMag(second): xs[0] xs[1] xs[2] and so on.
Please help, thank you!
You're close. The object you pass to writerow() should be a flat iterable containing the items you want to write to the row. Your attempt:
writeFile.writerow(['TimeMag (second):',xs])
...isn't flat, because it contains two elements, one of which (xs) is itself a list. Instead, you basically want to prepend your string ('TimeMag (second):') to the xs list. This should do what you're expecting:
writeFile.writerow(['TimeMag (second):'] + xs)

How can I concatenate text from multiple rows in a Schematiq table into a single value

In Microsoft Excel I have a Schematiq table that contains values in a number of rows:
I would like to concatenate all of the row values into a single value and store this in a cell delimited by the text "-colour-"
So from the example above, the desired output would be: red-colour-yellow-colour-pink-colour-green-colour-orange-colour-purple-colour-blue
Is this possible using a custom aggregate function?
Yes, this is possible using a custom aggregation function. Maybe you already tried something like this:
=tbl.Group(F7, , "A")
You'll have found that you get #VALUE! because Schematiq tries to add up the values in column A, and can't because they are not numbers.
When you supply a custom function to tbl.Group, it uses it on the first two values in the column, then that result and the next value, and so on. So to replicate the default behaviour you could use something like:
(x, y) => x + y
Based on your question though, you want to combine two text values using a function like this:
(x, y) => x & '-colour-' & y
..which would look like this as a call to tbl.Group:
=tbl.Group(F7, , "A", "(x, y) => x & '-colour-' & y")
You can then wrap this in a call to tbl.GetValue to put the answer straight into a cell.
Alternatively, you could do this, which gets all the values from the table column and uses txt.Join to combine them:
=txt.Join(tbl.GetValues(F7), "-colour-")
This is probably simpler in this specific case.
(incidentally, I'm part of the Schematiq team)

List comprehensions and matrices (raws)

Please, have a look at this constriction:
M = [[1,2,3],
[4,5,6],
[7,8,9]]
T = [row[1] for row in M]
print(T)
The result is [2, 5, 8]
I managed to find something here:
http://docs.python.org/py3k/tutorial/datastructures.html#nested-list-comprehensions
But I'm not satisfied with my understanding of this scheme with 'raw'.
Could you tell me where else in the documentation can I read about it?
By the way, why raw? It seems to be a column?
T = [row[1] for row in M]
This is a list comprehension. List comprehensions basically allow you to create lists on the fly while iterating through other iterables (in this case M).
The code above is more or less identical to this:
T = [] # create empty list that holds the result
for row in M: # iterate through all 'rows' in M
cell = row[1] # get the second cell of the current row
T.append(cell) # append the cell to the list
This is all just put together into a single line and a bit more efficient, but the basic idea is the same.
M is a matrix, but the internal representation you chose is a list of lists; or a list of rows. And in T you want to select a single column of the matrix although you have no direct access to columns in the matrix T. So you basically go through each row, take the cell of the column you are interested in and create a new list with the cells of your columns (as lists are usually horizontally aligned, you are strictly getting the transposed vector of your column).
You iterate through the rows and take second element of the row. Then you collect the extracted elements from the rows. It means that you have extracted the column.
Read the list comprehension from the right to the left. It says:
Loop through the matrix M to get the row each time (for row in M).
Apply the expression to the row to get what you need (here row[1]).
Iterate through the constructed results and build the list of them ([...]).
The last point makes it the list comprehension. The thing between the [ and ] is called a generator expression. You can also try:
column = list(row[1] for row in M)
And you get exactly the same. That is because the list() construct a list from any iterable. And the generator expression is such iterable thing. You can also try:
my_set = set(row[1] for row in M)
to get the set of the elements that form the column. The syntactically brief form is:
my_set = {row[1] for row in M}
and it is called set comprehension. And there can be also a dictionary comprehension like this:
d = { row[1]: True for row in M }
Here rather artificially, the row[1] is used as the key, the True is used as the value.

Resources