Ruby 2.3.1 sort_by function change? - ruby

Here's a small ruby script:
p "ruby #{ RUBY_VERSION }p#{ RUBY_PATCHLEVEL }"
p 100.times.collect{|i| i}.sort_by{|j| j % 1}
I would have expect the same result from a version to another. In my case, it's not. Here's the results
"ruby 2.2.3p173"
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
"ruby 2.3.1p112"
[99, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 0]
Is that normal?

Ruby doesn't guarantee you a sort order if the items are the same.
As to why the result changed between versions, this looks like a relevant change: ruby 2.3 tries to use a c-standard library provided implementation of quicksort in more cases than before.

Have a look at Is sort in Ruby stable?. The quick answer is no, it's not. What this means is that if two values are equivalent, in your case always equal to 0, you can't make any assumptions about where they go in relation to one another.

Related

Why is there a long list of PolygonVertexIndex without any negatives (In one Fbx file)?

I made a default cylinder using blender and exported it into fbx file. When I looked at the content of the file after converting it into json, I found the field "PolygonVertexIndex" (under "Geometry"-"Objects") contains:"3, 1, 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7" and " 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60".
These consistent positive indices series confuse me a lot since I believe fbx
PolygonVertexIndex store indices in "positive, positive, negative" (when the surface is triangular) or "positive, positive, positive, negative" (when the surface is quadrilateral). And I cannot find any information regarding consistent positive indices when I googled.
The whole list looks like:
["PolygonVertexIndex", [[0, 1, 3, -3, 2, 3, 5, -5, 4, 5, 7, -7, 6, 7,
9, -9, 8, 9, 11, -11, 10, 11, 13, -13, 12, 13, 15, -15, 14, 15, 17,
-17, 16, 17, 19, -19, 18, 19, 21, -21, 20, 21, 23, -23, 22, 23, 25, -25, 24, 25, 27, -27, 26, 27, 29, -29, 28, 29, 31, -31, 30, 31, 33, -33, 32, 33, 35, -35, 34, 35, 37, -37, 36, 37, 39, -39, 38, 39, 41, -41, 40, 41, 43, -43, 42, 43, 45, -45, 44, 45, 47, -47, 46, 47, 49, -49, 48, 49, 51, -51, 50, 51, 53, -53, 52, 53, 55, -55, 54, 55, 57, -57, 56, 57, 59, -59, 58, 59, 61, -61, 3, 1, 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19,
17, 15, 13, 11, 9, 7, -6, 60, 61, 63, -63, 62, 63, 1, -1, 0, 2, 4, 6,
8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42,
44, 46, 48, 50, 52, 54, 56, 58, 60, -63]], "i", []],
It can be seen that the indices are fine at the start of the list but goes weird later.
The list contains negative numbers to end a polygon and looks consistent. A polygon is not restricted to be a triangle or a quad, it can contain as many vertices as it needs.
One way to create a cylinder mesh is using quads on the sides and circles on both ends. In your case, the two long series of positive numbers are the two circles encoded as two big polygons containing 32 vertices each.

Ruby FFI read_array_of_uint8 returns different results for the same read_string

I'm trying to pinpoint a bug we're having and this is as far as I could come.
We're creating a memory pointer which is then filled by a C library:
hash_result_pointer = FFI::MemoryPointer.new(:uint8, 144)
CLibrary(hash_result_pointer)
We're testing this on a macOS High Sierra and on a Ubuntu Xenial via Docker. Here are the outcomes for both:
macOS High Sierra
p hash_result_pointer.read_string
# "\x0F\xE1\x11%\v\xC2)a#"
p hash_result_pointer.read_array_of_uint8(144)
# [15, 225, 17, 37, 11, 194, 41, 97, 64, 0, 32, 156, 191, 7, 38, 254, 119, 123, 104, 145, 2, 160, 137, 112, 10, 193, 71, 15, 3, 134, 245, 5, 6, 24, 234, 1, 100, 4, 188, 45, 158, 28, 120, 130, 42, 62, 152, 15, 1, 97, 48, 16, 0, 41, 125, 5, 4, 20, 142, 3, 10, 3, 156, 1, 65, 10, 122, 15, 52, 67, 52, 109, 38, 13, 18, 128, 47, 44, 53, 90, 23, 72, 32, 82, 56, 17, 42, 126, 57, 71, 71, 80, 9, 180, **65**, 80, 18, 9, 5, 56, 26, 17, 2, 121, 21, 52, 21, 92, 74, 19, 92, 83, 84, 45, 89, 123, 34, 117, 75, 89, 8, 7, 19, 12, 8, 5, 8, 8, 25, 1, 20, 14, 48, 3, 24, 57, 12, 32, 18, 90, 3, 35, 15, 34]
Ubuntu Xenial via Docker
p hash_result_pointer.read_string
# "\x0F\xE1\x11%\v\xC2)a#"
p hash_result_pointer.read_array_of_uint8(144)
# [15, 225, 17, 37, 11, 194, 41, 97, 64, 0, 32, 156, 191, 7, 38, 254, 119, 123, 104, 145, 2, 160, 137, 112, 10, 193, 71, 15, 3, 134, 245, 5, 6, 24, 234, 1, 100, 4, 188, 45, 158, 28, 120, 130, 42, 62, 152, 15, 1, 97, 48, 16, 0, 41, 125, 5, 4, 20, 142, 3, 10, 3, 156, 1, 65, 10, 122, 15, 52, 67, 52, 109, 38, 13, 18, 128, 47, 44, 53, 90, 23, 72, 32, 82, 56, 17, 42, 126, 57, 71, 71, 80, 9, 180, **66**, 80, 18, 9, 5, 56, 26, 17, 2, 121, 21, 52, 21, 92, 74, 19, 92, 83, 84, 45, 89, 123, 34, 117, 75, 89, 8, 7, 19, 12, 8, 5, 8, 8, 25, 1, 20, 14, 48, 3, 24, 57, 12, 32, 18, 90, 3, 35, 15, 34]
As you can see, there is one array element that differs by 1 (65 vs 66) between the two environments. I have no clue why this is happening and I also don't know what could cause this and where shall I look further. Would appreciate any tip!

Associating values from one array to another in Ruby

I'm building a simple program after learning a little bit of Ruby. I'm trying to associate values from one array to another here's what I've got so far.
ColorValues = ["Black", "Brown", "Red", "Orange", "Yellow", "Green", "Cyan", "Blue", "Violet", "Pink", "Grey"]
(0..127).each_slice(12) {|i| p i}
.each_slice returns these arrays
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
[24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
[36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]
[48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71]
[72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83]
[84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95]
[96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107]
[108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119]
[120, 121, 122, 123, 124, 125, 126, 127]
What I'm attempting to do is then take the returned arrays and associate them with each color in the ColorValues[] array
i.e.
"Black" = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
"Brown" = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
I'm sure there's a simple way of doing this I'm just not sure how to go about doing it.
Using Enumerable#zip and Hash::[]
colorValues = ["Black", "Brown", "Red", "Orange", "Yellow", "Green", "Cyan", "Blue", "Violet", "Pink", "Grey"]
Hash[colorValues.zip((0..127).each_slice(12))]
# => {"Black"=>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
# "Brown"=>[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
# "Red"=>[24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35],
# "Orange"=>[36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],
# "Yellow"=>[48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
# "Green"=>[60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71],
# "Cyan"=>[72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83],
# "Blue"=>[84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95],
# "Violet"=>[96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107],
# "Pink"=>[108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119],
# "Grey"=>[120, 121, 122, 123, 124, 125, 126, 127]}
You can use zip for that:
ColorValues.zip( (0..127).each_slice(12) )
Method #zip is convenient, but it turns out that your problem is so frequent in Ruby, that I have overloaded #>> operator on Array class to perform zipping into a hash. First, install y_support gem. Then,
require 'y_support/core_ext/array' # or require 'y_support/all'
h = ColorValues >> ( 0..127 ).each_slice( 12 ) # returns a hash like in falsetru's answer
h["Black"] #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

sort an array of arrays based on number of occurences in ruby

I want this integer array to be sorted in the right order based on its number of occurrences.
question = [[1, 7, 8, 9, 10, 11, 12, 19, 20, 21, 31, 32, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 81, 129, 132, 133, 134, 135, 136, 139], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 81, 129, 130, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141], [30], [77]]
question.flatten.uniq.size = 90
answer = sort_it(question)
answer = [77, 68, 8, 9, 10, 11, 12, 19, 20, 21, 31, 139, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 135, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 136, 66, 67, 7, 70, 71, 72, 73, 74, 75, 76, 1, 78, 79, 81, 129, 132, 133, 134, 45, 65, 32, 2, 3, 4, 5, 6, 13, 14, 15, 16, 17, 22, 23, 24, 25, 26, 27, 29, 33, 41, 69, 130, 137, 138, 140, 141, 30]
answer.uniq.size = 90
Here is my Ruby code:
def sort_it(actual)
join=[]
buffer = actual.dup
final = [ ]
(actual.size-2).downto(0) {|j|
join.unshift(actual.map{|i| i }.inject(:"&"))
actual.pop
}
ordered_join = join.reverse.flatten
final << ordered_join
final << buffer.flatten - ordered_join
final.flatten
end
Is this approach OK? Is there a more efficient approach?
EDIT:
As a tribute to tokland and niklas, edited the answer which was in the wrong order before.
Thanks!
Use group_by:
question.flatten.group_by{|x| x}.sort_by{|k, v| -v.size}.map(&:first)
Answer with sort_by{|k, v| -v.size} calls v.size every time elements are compared. More effective solution:
question.flatten.group_by(&:to_i).map{|k,v| [k, -v.size]}.sort_by(&:last).map(&:first)
Though size of array is easy to get, it is unnecessary expense (O(sorting algorithm) instead of O(n)), and this idiom is good to remember anyway for more expensive operations

import product data to magentogo online store

I tried to import the product data to my online store. I got the following errors..
Category does not exists in rows: 3, 4, 6, 9, 10, 12, 14, 15, 17, 18, 19, 21, 23, 24, 27, 28, 31, 35, 36, 39, 43, 51, 52, 59, 60, 63, 64, 66, 71, 72
Invalid value for Attribute Set column (set does not exists?) in rows: 3, 9, 14, 18, 23, 27, 31, 35, 39, 43, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59, 63, 67, 68, 69, 70, 71
Orphan rows that will be skipped due default row errors in rows: 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 19, 20, 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 46, 52, 53, 54, 60, 61, 62, 64, 65, 66, 72
Errors limit (100) reached. Please fix errors and re-upload file
Checked rows: 72, checked entities: 27, invalid rows: 70, total errors: 100
Could you please tell me what is causing this?
I faced same problems but i rectified them with following steps.
Error-1--Category does not exists in rows: 3, 4, 6, 9, 10, 12, 14, 15, 17, 18, 19, 21, 23, 24, 27, 28, 31, 35, 36, 39, 43, 51, 52, 59, 60, 63, 64, 66, 71, 72
Solution: The problem is the categories to which the products attached to are not present in the backend so create those categories. Once this done the error disappears
Error-2 -- Invalid value for Attribute Set column (set does not exists?) in rows: 3, 9, 14, 18, 23, 27, 31, 35, 39, 43, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59, 63, 67, 68, 69, 70, 71
Solution:_attribute_set column is a compulsory field it should be there with a value
while uploading the products.
Error-3 Orphan rows that will be skipped due default row errors in rows: 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 19, 20, 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 46, 52, 53, 54, 60, 61, 62, 64, 65, 66, 72 Errors limit (100) reached. Please fix errors and re-upload file Checked rows: 72, checked entities: 27, invalid rows: 70, total errors: 100
Solution: This error disappears once the two above is fixed.
Thank you.
Happy coding.

Resources