Bağlantılı değerleri her zaman toplam% 100 olan X yüzde kaydırıcılarını gösteren bir kullanıcı arayüzü için algoritma


11

Oluşturduğum bir sistem, her biri 0-100 ölçeğine sahip bir dizi UI kaydırıcısını (sayı değişir) içerir. Kaydırıcıyla, bir öğeyi tutup bir ses düzeyi denetimi gibi yukarı ve aşağı sürüklediğiniz bir kullanıcı arayüzü anlamına gelir. Her zaman toplam 100 olmasını sağlayan bir algoritma ile bağlanırlar. Bu nedenle, bir kaydırıcı yukarı hareket ettirildiğinde, diğerleri aşağıya, sonunda sıfıra hareket eder. Biri aşağı hareket ettirildiğinde, diğerleri yukarı hareket eder. Her zaman toplam 100 olmalıdır. Yani burada kaydırıcıların çeşitli değerleri vardır, ancak toplam% 100'dür:

----O------ 40
O----------  0
--O-------- 20
--O-------- 20
--O-------- 20

İlk kaydırıcı 40'dan 70'e kadar YUKARI hareket ederse, diğerleri (kaydırıcı sürüklendikçe) değer olarak AŞAĞI hareket etmelidir. Üç sürgünün 20'den 10'a değiştiğini ve alçaltılamadığından biri sıfırda kaldığını unutmayın.

-------O--- 70
O----------  0
-O--------- 10
-O--------- 10
-O--------- 10

Tabii ki herhangi bir kaydırıcı 0 veya 100'e ulaştığında, daha fazla hareket edemez, bu da kafamın gerçekten acımaya başladığı yerdir. Dolayısıyla, bir kaydırıcı daha yükseğe hareket ederse, diğerleri daha aşağı hareket eder, ancak bunlardan herhangi biri sıfıra ulaştığında, yalnızca henüz sıfıra ulaşmamış kalanlar daha düşük hareket edebilir.

Ben burada bu soru uygulama değil algoritmaya özgü olarak soruyorum. FWIW platformu Android Java, ancak bu özellikle alakalı değil.

İlk bıçakla aldığım yaklaşım, hareket eden kaydırıcının yüzde değişimini hesaplamaktı. Daha sonra bu değişikliği böldüm ve (diğer yönde) diğer kaydırma değerlerine uyguladım. Ancak sorun, yüzdelerin kullanılması ve çarpılmasıyla, herhangi bir kaydırıcı sıfıra ulaştığında, bir daha asla sıfırdan artırılamaz - bunun net sonucu, tek tek kaydırıcıların sıfıra yapışmasıdır. Yuvarlama sorunlarından kaçınmak için 0 - 1.000.000 aralığında kaydırıcılar kullandım ve bu yararlı görünüyor, ancak henüz tüm senaryoları iyi işleyen bir algoritma oluşturmadım.


2
Benzer sorular UX sitesinde de sorulmuştur, ancak IMHO'ya özellikle tatmin edici bir şekilde cevap verilmemiştir. İyi bir çözüm olup olmadığını merak ediyorum. Dürüst olmakla birlikte, kaydırıcıların birbirine bağlı olmasının, kullanıcı için bile değerinden daha fazla soruna neden olduğunu görüyorum - zaten girdiğiniz değerleri değiştirmeye devam ettiğiniz için, istediğiniz dağıtımla sonuçlanmak zorlaşıyor Git.
Daniel B

1
Bir öneri, kullanıcının esasen kaydırıcıların birbirine bağlandığı ve diğerinin olmadığı (ve "göreceli moda" geri dönme) dağıtımı yeniden normalleştireceği iki mod arasında geçiş yapmasına izin vermek olacaktır. Bu, bahsettiğiniz sorunlardan bazılarının yan adımlara gitmesine izin verir, ancak kullanıcı arayüzüne o kadar karmaşıklık katar ki, kullanıcının değerleri
Daniel B

Kesinlikle haklısınız, kullanıcının kısmında çok uğraşmak gerekiyor, ancak bu durumda, kaydırıcıların sorunları temsil ettiği bir anket uygulamasıdır, bu yüzden soru değerlerin göreli ağırlıkları hakkında TÜMdür.
Ollie C

1
Anlıyorum ... Sorunum gerektirecektir her 60/30/10 bölünmüş gibi bir şey ifade sadece budur daha 30/10 parçası ile işe yaramaz çünkü ne zaman, 3'ten eylemleri 60 civarında hareket ediyor. Daha büyük listelerle gittikçe kötüleşir ve sadece son derece belirsiz girdiler için gerçekten uygundur, çünkü asla kafanızdaki numaraya ulaşamazsınız.
Daniel B

2
Bir UX noktasından, toplam puanın kaydırıcıların yanına çok sayıda sunulmasını öneririm. Bir kaydırıcıyı yukarı kaydırdığınızda, toplam puan "100" üzerinde artar ve "sonraki" düğmeniz ne olursa olsun, kullanıcı toplam puanı azaltmak için başka bir kaydırıcıyı aşağı kaydırıncaya kadar devre dışı kalır. Kullanıcının bir kaydırıcıyı yukarı kaydırdığında diğer 4 kaydırıcıdan hangisini azaltmak istediğini asla bilemezsiniz, bu yüzden denemeyin.
Graham

Yanıtlar:


10

Açgözlü algoritma

Bir kaydırıcı yukarı (aşağı) hareket ettiğinde, diğerlerinin aşağı (yukarı) hareket etmesi gerekir. Her birinin hareket edebileceği bir alanı vardır (aşağı için - konumları, yukarı için: 100 konumu).

Yani bir kaydırıcı hareket ettiğinde, diğer kaydırıcıları alın, taşıyabilecekleri alana göre sıralayın ve basitçe aralarında yineleyin.

Her bir yinelemede, kaydırıcıyı gerekli yöne (sola kaydırmak için toplam / sıradaki sola kaydırmak için) veya taşıyabileceği mesafeye (hangisi daha küçükse) kadar hareket ettirin.

Bu karmaşıklık açısından lineerdir (sıralandıktan sonra aynı sıralı kuyruğu tekrar tekrar kullanabildiğiniz için).

Bu senaryoda, hiçbir kaydırıcı takılmaz, hepsi olabildiğince hareket etmeye çalışır, ancak sadece adil paylarına kadar.

Ağırlıklı hareket

Farklı bir yaklaşım, yapmaları gereken hareketi ağırlıklandırmak olacaktır. Ben düşünüyorum bu deyimi "0 takılıp kaydırıcılar" senin bakılırsa, yapmaya çalıştığı budur. IMHO bu daha doğal, daha fazla ayar yapmanız gerekiyor.

Yine spekülasyon, farklı kaydırıcıların hareketlerini konumlarına göre ağırlıklandırmaya çalıştığınızı söyleyebilirim (Bu, doğrudan 0 problemde sıkışıp kalmanıza dönüşür). Ancak, kaydırma konumunu başlangıçtan veya bitişten farklı yönlerden görebileceğinizi unutmayın. Eğer azalırken başlangıçtan başa ve artış sırasında sondan başa ağırlık verirseniz, probleminizden kaçınmalısınız.

Bu, terminolojide önceki bölüme oldukça benzer - kaydırıcıların konumuna göre hareket etmeyi, bu yönde hareket etmek için bıraktıkları boşlukla ağırlıklandırmayın .


1
Daha derine baktım ve "sıkışmış" olanların sıkışıp kalmadıkları ortaya çıkıyor, ancak sadece bu kadar düşük değerlere sahip, yüzde değişiminin neredeyse hiçbir etkisi yok - bir kaydırıcının hareket ettiği değer değerine göre. Ben karşıt değeri kullanmak için öneri oldukça iyi çalışabilir şüpheli, ben sadece toplam değeri 100 tutmak zorunda. Biraz netlik enjekte için teşekkürler.
Ollie C

1

Benim alacağım yaklaşım biraz farklıdır ve her kaydırıcının farklı bir iç temsilini kullanmayı içerir.

  1. her kaydırıcı, o kaydırıcı için ağırlık faktörü olarak kullanılan 0..100 (X) değerinden herhangi bir değer alabilir (% değil)

  2. toplam rakamı almak için tüm kaydırma değerlerini topla (T)

  3. her kaydırıcının görüntülenen değerini belirlemek için YUVARLA (X * 100 / T) kullanın

  4. bir kaydırıcı yukarı veya aşağı hareket ettirildiğinde, yalnızca bir kaydırıcının değerini değiştirirsiniz ; bu kaydırıcının ağırlığı diğer tüm kaydırıcılara göre artacak veya azalacaktır ve yukarıdaki kireç diğer tüm kaydırıcılardaki değişikliğin mümkün olduğunca eşit şekilde yayılmasını sağlayacaktır.


Kullanıcı esas olarak az ya da çok kesin kesirler yapmakla ilgileniyorsa, bu iyi bir arayüz olacaktır. Ancak, bunun diğer slaytların konumlarıyla orantılı hareket etmesinden işlevsel olarak nasıl farklı olduğunu göremiyorum.
Sıradan

1

Sanırım, mevcut değeri, yuvarlama hataları getiren yüzdeler yüzdeleri veren 'taşınan' kaydırıcıdaki değişimin yüzdesi ile ayarlamaya çalışarak aşırı karmaşıklaştığınızı düşünüyorum.

Sadece toplam 100 değeriyle uğraştığınızı bildiğiniz için, işleri tamsayı olarak tutar ve 100'den geriye doğru çalışır, yuvarlama ile ilgili ciddi karışıklıklardan kaçınırım. (Aşağıdaki örnekte, herhangi bir yuvarlamayı sonunda tamsayı olarak ele alıyorum)

Benim tekniğim kaydırıcıları basit 0-100 olarak ayarlamak olacaktır. Ne kadar yeniden dağıtılacağını bulmak için 'yeni' değeri 100'den çıkarın, ağırlıklarına göre diğer kaydırıcılar arasında dağıtın, sonra temizleyin)

Bu, bildiğim kadarıyla geçerli bir Android kodu değil: p

// see how much is "left" to redistribute
amountToRedistribute = 100 - movedSlider.value

//What proportion of the original 100% was contained in the other sliders (for weighting)
allOtherSlidersTotalWeight = sum(other slider existing values)

//Approximately redistribute the amount we have left between the other sliders, adjusting for their existing weight
for each (otherSlider)
    otherSlider.value = floor(otherSlider.value/allOtherSlidersWeight * amountToRedistribute)
    amountRedistributed += otherSlider.value

//then clean up because the floor() above might leave one or two leftover... How much still hasn't been redistributed?
amountLeftToRedistribute -= amountRedistributed

//add it to a slider (you may want to be smarter and add in a check if the slider chosen is zero, or add it to the largest remaining slider, spread it over several sliders etc, I'll leave it fairly simple here)
otherSlider1.value += amountLeftToRedistribute 

Bu, herhangi bir 0 veya 100 değerini özüyle ele almalıdır


0

Round Robin yaklaşımı ne olacak? Bir kaydırıcıya değer eklemenin eşinden azalacağını garanti eden bir işlem oluşturun. ve tam tersi.

Sonra her zaman bir kaydırıcı değişikliği işlemi farklı bir eş kaydırıcı ile çalıştırın (Eş kaydırıcıyı sırayla döndüren bir yineleyici oluştururdum). Eş kaydırıcı sıfırsa, bir sonrakine geçin.


0

@Ordous'tan gelen büyük Açgözlü Algoritma cevabını detaylandırmak için. İşte adımların dökümü.

  1. Kaydırıcıyı Taşı
  2. Ayrıntılar differenceAmount o kadar hareket newValue - OldValue (pozitif değer aracı bu yukarı ve diğer sürgü aşağı hareket ettirmek için ihtiyaç ve tersi)
  3. Sıralama diğerleri gelen listede en az çoğuna ait mesafeye hareket ettiklerini CAN gerektirdiği doğrultuda differenceAmount pozitif veya negatif olma.
  4. Set amountToMove = differenceAmount / kalan OthersCount
  5. Döngü boyunca ve her kaydırıcıyı ya da miktarı için hareket veya amountToMove . Hangisi daha küçükse
  6. Kaydırıcı miktarı çıkarma hareket yaptığı gelen amountToMove ile bölün yeni kalan OthersCount
  7. İşiniz bittiğinde, farkı diğer kaydırıcılar arasında başarıyla dağıttınız.

Burada harika bir cevap. stackoverflow.com/a/44369773/4222929
Sean

-3

Basit bir teknik, kaydırıcı değerlerinin toplamına göre kaydırıcı değerlerinin yüzdelerini hesaplamak ve daha sonra kaydırıcı değerlerini ilgili hesaplanan yüzdelere yeniden atamaktır. bu şekilde kaydırıcı değerleri yeniden ayarlanır;

slider1.value = (slider1.value / sumOfSliderValues) * 100 ;
slider2.value = (slider2.value / sumOfSliderValues) * 100 ;
slider3.value = (slider3.value / sumOfSliderValues) * 100 ;

Her ne kadar yuvarlama hatası verirse de, kaydırıcı değerlerinin tam olarak ve her zaman 100'e kadar toplamasına ihtiyaç duymamız durumunda işlenebilir.

Bunu angularjs kullanarak göstermek için bir keman kurdum. Lütfen demoyu ziyaret edin


2
... Jeffrey'in cevabı bu. Tekrarları önlemek için lütfen önce diğer yanıtları okuyun.
Jan Doggen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.