How get a list from List of Lists - arrays

How get a list from array of arrays?
I have a List of Lists, like: [[1,2,3],[1,2,3],[1,2,3]].
I want to have a List that contains all first elements from my List.
For example in my example, I want to have a list = [1,1,1].

If you also might want to get the second/third elements of each List, you can also use transpose:
def input = [[1,2,3],[1,2,3],[1,2,3]]
def output = input.transpose()
// All the lists are joined by element index
assert output == [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
// Grab the first one (1,1,1)
assert output[ 0 ] == [ 1,1,1 ]

If you know you always have an list of lists (i.e. the inner list always exists), you could do it like this:
def lists = [[1,2,3],[1,2,3],[1,2,3]]
def result = lists.collect { it[0] }
assert result == [1,1,1]

Related

how to convert a list of arrays to a python list

Given a number I want to split it separate but even-ish list which I can do :
import numpy as np
pages = 7
threads = 3
list_of_pages = range(1,pages+1)
page_list = [*np.array_split(list_of_pages, threads)]
Returns:
[array([1, 2, 3]), array([4, 5]), array([6, 7])]
I would like it to return a list of lists instead, ie:
[[1,2,3],[4,5],[6,7]]
I was hoping to do something like this (below doesnt work):
page_list = np.array[*np.array_split(list_of_pages, threads)].tolist()
is that possible or do I need to just loop through and convert it?
Assuming page_list is a list of ndarray, then you can convert to python list like this,
[x.tolist() for x in [*page_list]]
# [[1, 2, 3], [4, 5], [6, 7]]
#zihaozhihao gave a inline solution. You can also write a for loop to iterate over every item in page_list and convert it to list
list_of_lists = [ ]
for x in [*page_list]]:
list_of_lists.append(x.tolist())

Sort an array of arrays by the number of same occurencies in Ruby

This question is different from this one.
I have an array of arrays of AR items looking something like:
[[1,2,3], [4,5,6], [7,8,9], [7,8,9], [1,2,3], [7,8,9]]
I would like to sort it by number of same occurences of the second array:
[[7,8,9], [1,2,3], [4,5,6]]
My real data are more complexes, looking something like:
raw_data = {}
raw_data[:grapers] = []
suggested_data = {}
suggested_data[:grapers] = []
varietals = []
similar_vintage.varietals.each do |varietal|
# sub_array
varietals << Graper.new(:name => varietal.grape.name, :grape_id => varietal.grape_id, :percent => varietal.percent)
end
raw_data[:grapers] << varietals
So, I want to sort raw_data[:grapers] by the max occurrencies of each varietals array comparing this value: grape_id inside them.
When I need to sort a classical array of data by max occurencies I do that:
grapers_with_frequency = raw_data[:grapers].inject(Hash.new(0)) { |h,v| h[v] += 1; h }
suggested_data[:grapers] << raw_data[:grapers].max_by { |v| grapers_with_frequency[v] }
This code doesn't work cos there are sub arrays there, including AR models that I need to analyze.
Possible solution:
array.group_by(&:itself) # grouping
.sort_by {|k, v| -v.size } # sorting
.map(&:first) # optional step, depends on your real data
#=> [[7, 8, 9], [1, 2, 3], [4, 5, 6]]
I recommend you take a look at the Ruby documentation for the sort_by method. It allows you to sort an array using anything associated with the elements, rather than the values of the elements.
my_array.sort_by { |elem| -my_array.count(elem) }.uniq
=> [[7, 8, 9], [1, 2, 3], [4, 5, 6]]
This example sorts by the count of each element in the original array. This is preceded with a minus so that the elements with the highest count are first. The uniq is to only have one instance of each element in the final result.
You can include anything you like in the sort_by block.
As Ilya has pointed out, having my_array.count(elem) in each iteration will be costlier than using group_by beforehand. This may or may not be an issue for you.
arr = [[1,2,3], [4,5,6], [7,8,9], [7,8,9], [1,2,3], [7,8,9]]
arr.each_with_object(Hash.new(0)) { |a,h| h[a] += 1 }.
sort_by(&:last).
reverse.
map(&:first)
#=> [[7.8.9]. [1,2,3], [4,5,6]]
This uses the form of Hash::new that takes an argument (here 0) that is the hash's default value.

How do I remove duplicate attributes from an array based on fields of the objects in the array?

I'm using Rails 5 and Ruby 2.4 I have an array of objects, each object having the fields
name
member_id
I wish to scan through my array and eliminate duplicate items, taht is, items whose fields "name" and "member_id" already match something else in teh array. How do I do this? I realize I can check if the array already contains an item by using
results.any?{|a| a.name.eql?(name) && a.member_id == member_id}
But I'm unsure how to use the above to eliminate duplicates. Also, if there are duplicates, I still want to keep one of the items with the unique name/member_id combination.
Ruby's uniq is an option. For instance, suppose I want to compare the subarray elements in the following by their values at subindices 0 and 2. I can create a comparison object comprised of those items and use it with uniq's block option:
a = [
['one', 1, 1],
['two', 2, 2],
['one', 2, 1],
['two', 2, 2],
['one', 1, 2],
]
p a.uniq { |elt| [elt[0], elt[2]] } # => [["one", 1, 1], ["two", 2, 2], ["one", 1, 2]]

Neo4j Cypher - Collect two array values return one object

I have multiple nodes with same label. The node properties have two arrays. I want join both array values to an object or a map.
Example:
Array one: [1,2,3,4,5]
Array two: [5,4,3,2,1]
I want to return result as {output:[{1,5},{2,4},{3,3},{4,2},{5,1}]} so a total of 5 objects in that output result.
Is this possible in Cypher?
WITH [1,2,3,4,5] AS array_one, [5,4,3,2,1] AS array_two
UNWIND RANGE(0, SIZE(array_one) - 1) AS i
WITH [array_one[i], array_two[i]] AS output
WITH COLLECT(output) AS output_list
RETURN {outputs: output_list}
That will give you a map, whose sole value is a list of lists. If you want to dynamically build a list of maps instead (your question's syntax is ambiguous), you will have to look into apoc, Cypher doesn't natively support dynamic key assignment.
APOC procedures may be the way to go on this one. In the Collection Functions section, the procedure you want is apoc.coll.zip([list1],[list2]). It is similar to what you want, but not exact. Rather than returning a list of objects, it will return a list of list pairs:
with [1,2,3,4,5] as list1, [5,4,3,2,1] as list2
call apoc.coll.zip(list1,list2) yield value
return {outputs:value}
// returns {outputs:[[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]}
Regarding your desired output, objects in Cypher are like JSON objects and consist of key/value pairs, so it is impossible to return it in the format you're describing. You can test this for yourself.
// this works just fine
return {output: [[1,2]]}
// this causes a syntax error
return {output: [{1,2}]}
Array of maps
You can generate a map containing an array of maps without using APOC:
WITH [1,2,3,4,5] AS a1, [5,4,3,2,1] AS a2
RETURN {output: REDUCE(s = [], i IN RANGE(0, SIZE(a1)-1) | s + {one: a1[i], two: a2[i]})} AS res;
The output is:
{output:[{"one":1,"two":5},{"one":2,"two":4},{"one":3,"two":3},{"one":4,"two":2},{"one":5,"two":1}]}
Array of arrays
To generate a map containing an array of arrays:
WITH [1,2,3,4,5] AS a1, [5,4,3,2,1] AS a2
RETURN {output: REDUCE(s = [], i IN RANGE(0, SIZE(a1)-1) | s + [[a1[i], a2[i]]])} AS res;
The output is:
{output:[[1,5],[2,4],[3,3],[4,2],[5,1]]}

Splitting an Array into Sub-Arrays in Swift [duplicate]

This question already has answers here:
In Swift, an efficient function that separates an array into 2 arrays based on a predicate
(7 answers)
Closed 6 months ago.
Problem
Given an array of values how can I split it into sub-arrays made of elements that are equal?
Example
Given this array
let numbers = [1, 1, 1, 3, 3, 4]
I want this output
[[1,1,1], [3, 3], [4]]
What I am NOT looking for
A possible way of solving this would be creating some sort of index to indicate the occurrences of each element like this.
let indexes = [1:3, 3:2, 4:1]
And finally use the index to rebuild the output array.
let subsequences = indexes.sort { $0.0.0 < $0.1.0 }.reduce([Int]()) { (res, elm) -> [Int] in
return res + [Int](count: elm.1, repeatedValue: elm.0)
}
However with this solution I am losing the original values. Of course in this case it's not a big problem (an Int value is still and Inteven if recreated) but I would like to apply this solution to more complex data structures like this
struct Starship: Equatable {
let name: String
let warpSpeed: Int
}
func ==(left:Starship, right:Starship) -> Bool {
return left.warpSpeed == right.warpSpeed
}
Final considerations
The function I am looking for would be some kind of reverse of flatten(), infact
let subsequences: [[Int]] = [[1,1,1], [3, 3], [4]]
print(Array(subsequences.flatten())) // [1, 1, 1, 3, 3, 4]
I hope I made myself clear, let me know should you need further details.
// extract unique numbers using a set, then
// map sub-arrays of the original arrays with a filter on each distinct number
let numbers = [1, 1, 1, 3, 3, 4]
let numberGroups = Set(numbers).map{ value in return numbers.filter{$0==value} }
print(numberGroups)
[EDIT] changed to use Set Initializer as suggested by Hamish
[EDIT2] Swift 4 added an initializer to Dictionary that will do this more efficiently:
let numberGroups = Array(Dictionary(grouping:numbers){$0}.values)
For a list of objects to be grouped by one of their properties:
let objectGroups = Array(Dictionary(grouping:objects){$0.property}.values)
If you could use CocoaPods/Carthage/Swift Package Manager/etc. you could use packages like oisdk/SwiftSequence which provides the group() method:
numbers.lazy.group()
// should return a sequence that generates [1, 1, 1], [3, 3], [4].
or UsrNameu1/TraverSwift which provides groupBy:
groupBy(SequenceOf(numbers), ==)
If you don't want to add external dependencies, you could always write an algorithm like:
func group<S: SequenceType where S.Generator.Element: Equatable>(seq: S) -> [[S.Generator.Element]] {
var result: [[S.Generator.Element]] = []
var current: [S.Generator.Element] = []
for element in seq {
if current.isEmpty || element == current[0] {
current.append(element)
} else {
result.append(current)
current = [element]
}
}
result.append(current)
return result
}
group(numbers)
// returns [[1, 1, 1], [3, 3], [4]].
Let's assume that you have an unsorted array of items. You will need to sort the initial array then you will have something like this:
[1, 1, 1, 3, 3, 4]
After that you will initialize two arrays: one for storing arrays and another one to use it as a current array.
Loop through the initial array and:
if the current value isn't different from the last one, push it to the current array
otherwise push the current array to the first one then empty the current array.
Hope it helps!
Worth mentioning, using Swift Algorithms this is now a one-liner:
import Algorithms
let numbers = [1, 1, 1, 3, 3, 4]
let chunks: [[Int]] = numbers.chunked(by: ==).map { .init($0) }
print(chunks) // [[1, 1, 1], [3, 3], [4]]

Resources